What's underneath Array.new(10, &:next) in ruby [duplicate] - arrays

This question already has answers here:
What does map(&:name) mean in Ruby?
(17 answers)
Closed 5 years ago.
I was looking that in Ruby there are a lot of ways to declare arrays objects like:
[1,2,3]
Array.new(3){|i| i+1}
Even with more trickier ways like:
Array.new(3, &1.method(:+))
Where the &1.method(:+) means that the object 1 (reference by value) is responding to the method + directly referenced, so every time (3 times in this case) the array is executing the block, the object increments by 1. I would appreciate any correction if I'm wrong on my analysis here.
So, passing that, there is this case that I'm not completely following:
Array.new(3, &:next)
The question is:
What's the & doing in this case? I can guess that is a reference to some value directly but I don't know which one exactly. And after the &, how the :next is acting in this case.
Beforehand, I really appreciate your help. I'm getting the grasp of Ruby and I'm liking it even more!

& is a shortcut for Symbol#to_proc in this case. A corresponding full version is:
Array.new(3) { |i| i.next }
#=> [1, 2, 3]
The instance below can help you understanding how does it work:
Array.new(3, &(:next.to_proc))
#=> [1, 2, 3]

Related

Sum of elements of two integer array in a single string array in Swift

Have a function Arr(strArr) read the array of strings stored in strArr which will contain only two elements, both of which will represent an array of positive integers. For example of strArr is ["[1, 2, 5, 6]", "[5, 2, 8, 11]"], and goal for this is to add the elements in corresponding locations from both arrays. For the example input, the program should do the following additions: [(1 + 5), (2 + 2), (5 + 8), (6 + 11)] which then equals [6, 4, 13, 17]. Return this resulting array in a string format with each element separated by a hyphen: 6-4-13-17.
If the two arrays do not have the same amount of elements, then simply append the remaining elements onto the new array.
Examples
Input: ["[5, 2, 3]", "[2, 2, 3, 10, 6]"]
Output: 7-4-6-10-6
Input: ["[1, 2, 1]", "[2, 1, 5, 2]"]
Output: 3-3-6-2
Thank you for your help.
The question seems obviously a homework exercise, and as was pointed out in comments that's not what StackOverflow is for; however, I know a lot of students who struggle to know even how to approach a problem. I think helping with that is a good thing, so I won't give a solution to the problem, but rather advice about approaching it.
The general formula that works for most problems is simple: Break the problem into smaller sub-problems, and solve each of those independently, then combine the sub-solutions. If any of those sub-problems are too complicated, repeat the process for those, and so on.
Homework problems, and a lot of real world problems, usually break down into three main sub-problems:
Transform some input into a more conveniently computable form.
Process the transformed input into some computed outputs.
Transform the computed outputs into a specified format.
Applied to your problem, you have:
How to parse a specially formatted string into an array of integers.
How to sum corresponding elements of two arrays, taking into account they may be of different lengths, to produce an array of sums.
How to transform an array of integers into a specially delimited string output.
The solution to your top-level problem will involve applying the sub-solutions in that order, but you don't have to solve them in that order. If you're having difficulty with getting started with the first one, solve one of the easier sub-solutions first to get some momentum. Psychology is actually quite important in problem solving. Believing you can solve it is half of actually solving it, so solve the easier problems first to get that factor working in your favor.
Maybe you regard the sub-problem 3 as the easiest to solve: So write a function place-holder for it (aka, a "stub function"), and make up some input data to test it. This would lead you to write something like this:
func formatOutput(from intArray: [Int]) -> String
{
// Your implementation will go here
}
let actual = formatOutput(from: [1, 2, 3, 4])
let expected = "1-2-3-4"
// If you're doing this in a playground, app, or command line tool
if actual != expected {
fatalError("FAILED: \"\(actual)\" != \"\(expected)\"")
}
else { print("Yay! Passed!") }
// If you're using XCTest
XCTAssertEqual(actual, expected)
That won't even compile yet, because formatOutput has to return something, and it doesn't yet. The key thing is that you've written your usage code first, and expressed in code what you expect. Now focus on the guts of formatOutput. If you want to take a Test Driven Development approach (TDD), maybe at first just return an empty string from formatOutput so you can be sure the code compiles and you see a failing test. Then implement it correctly if you know how, or in small steps if you're not clear on what to do. As you get the exact thing you're testing for working, you can keep adding more tests and improving formatOutput until you've verifiably got it doing everything it's supposed to do. Remember the KISS principle: "Keep It Simple, Stupid!" Don't over-think the solution, and save doing it "cleverly" for another day, which often never comes because the simple thing was sufficient.
At that point you have one of the sub-problems solved, so you move on to the next, following the same pattern. And the next, until all the parts are solved. Then put them together.
You'll note that sub-problem 2 has a bit of an extended description, especially the part specifying that the arrays may be of different lengths. Unless you already know how to solve that problem as stated, that sort of thing indicates it's a good candidate to be broken into yet simpler problems:
2a. How to sum corresponding elements of two arrays of the same length.
2b. How to modify 2a to handle arrays of different lengths.
2b can be done a few different ways:
2.b.1. Apply 2.a to sub-arrays of common length, then handle the remaining part of the longer one separately
OR
2.b.2. Enlarge the shorter array so that it is the same length as the longer one, so 2.a can be applied unmodified.
OR
2.b.3. Modify 2.a so that it can treat the shorter array as though it were the same length as the longer one, without actually copying or adding new elements.
OR
2.b.4. Modify 2.a so that it doesn't have to do anything special for different lengths at all. Hint: think more about the output and its length than the inputs.
When faced with alternatives like that, in the absence of any external constraints that would make one option preferred over the others, pick the one that seems simplest to you (or the most interesting, or the one you think you'd learn the most from). Or if you have time, and want to get the most out of the exercise, implement all of them so you can learn how they are all done, and then pick the one you like best for your final code.
func getResult(strArr: [String]) -> String {
let intArray1 = (try? JSONDecoder().decode([Int].self, from: Data(strArr[0].utf8))) ?? []
let intArray2 = (try? JSONDecoder().decode([Int].self, from: Data(strArr[1].utf8))) ?? []
var arrayResult = zip(intArray1,intArray2).map(+)
let commonCount = arrayResult.count
arrayResult.append(contentsOf: intArray1.dropFirst(commonCount))
arrayResult.append(contentsOf: intArray2.dropFirst(commonCount))
return arrayResult.map(String.init).joined(separator: "-")
}
let result1 = getResult(strArr : ["[5, 2, 3]", "[2, 2, 3, 10, 6]"])
let result2 = getResult(strArr : ["[1, 2, 1]", "[2, 1, 5, 2]"])
You can use this function to get your desired result.

replacing the value of an element in an array without creating a new array

I'm learning Ruby and have been practicing by solving problems on Codewars and Leetcode. I've come across this problem in Leetcode where it is asking me to, given an array and a value, modify the array in place by removing an occurrence of the value given in the array. Pretty simple! I was able to solve it- but, this curious thing happened and I don't know why!
Here's my code:
def remove_element(nums, val)
nums.each_with_index do |num, index|
if num == val
nums[index] = nil
end
end
nums.compact!
nums.length
end
You can see here that on line 4 I've written "nums[index] = nil", and this worked just fine for me. However, for the longest time I was trying to solve the challenge by writing "num = nil". What doesn't make sense to me is, why does "nums[index]" work and not "num"? Don't they refer to the same thing?
Answer from Dave Newton:
num is a block-local variable, nums is the array. Modifying a local parameter is different than accessing a reference. As another example, say that the array was filled with objects. num.some_property = 5 would modify the property of the array entry, num = SomeNewObject.new would just create a new object and not modify the array entry. Same thing would happen if you were calling a function.

Swift get tailing subarray [duplicate]

This question already has answers here:
How to copy end of the Array in swift?
(6 answers)
Closed 6 years ago.
Swift's implementation of arrays is throwing me for a loop again! (Haw, haw.) All I want is to take an array of arbitrary length and get a new array (or an array slice) from it that has the first element removed.
Why is this so hard?
I just want to be able to do something like this:
let suffix = someArray.suffixFrom(1)
But I can't figure out how to do this. It seems the closest method I've found requires knowing the length of the array, which I don't know because it's computed inline and I really really hate having to split such a simple concept up into a bunch of variables and lines.
Elaboration:
I have a string split by colons (:) and I just want to create a Set containing all the :-delimited components excluding the first one.
So that a string "one:two:three" would return a set containing ["two", "three"]. Since I can create a Set from an array, all I really need is to get the suffix of the array, but I don't know how many components there are because it's inline:
return Set(attributeName?.componentsSeparatedByString(":").suffixFrom(1))
Why does Swift make this so hard?
Edit: Before a bunch of you suggest it, I'm well aware I could extend the array class to do this myself, but I'm writing a framework and I don't want to do that, and I also don't want to have to write a bloody utility function to do something so darned simple.
The CollectionType.dropFirst(_:) does exactly what you need, with the exact syntax you're looking for.
let suffix = someArray.dropFirst(1)

Modifying array items in Swift [duplicate]

This question already has answers here:
Swift Object reference to array?
(4 answers)
Closed 6 years ago.
I found some really strange behavior in Swift. Here's the code:
var array2d: [[Int]] = [[1]]
print(array2d) // prints [[1]]
var first = array2d[0]
first.append(2)
print(array2d) // still prints [[1]]!!!
I would totally expect the last line to print [[1, 2]]. I can't explain the current behavior. I'd expect array2d[0] to return a reference to the first item, or possibly a copy of that reference. In either case, modifying that object should modify array2d. But that's not what's happening.
If, however, I update the array like this:
array2d[0].append(2)
it then prints [[1, 2]], as expected.
Can someone please explain this for me?
How arrays are referenced/passed around/copied in swift is a point of a lot of contention, take a look at this link.
In essence what is happening is that var first = array2d[0] is taking a copy of the array at that index as opposed to creating a reference as you were expecting. Hence accessing the array with the subscript notation allows to you to correctly alter the array but creating a new variable doesn't.

Object Reverse Action Script 3.0 [duplicate]

This question already has answers here:
What's happening when I use for(i in object) in AS3?
(2 answers)
Closed 8 years ago.
When i try to print the object, it simply print in reverse.
Code:
var marcos:Object = new Object();
marcos.nome = "Marcos";
marcos.ano = 19;
for (var prop in marcos)
{
trace(prop + ":" + " " + marcos[prop]);
}
Output:
ano: 19
nome: Marcos
I had search in the adobe documentation about object and for each but nothing seems ot explain that.
When i try to put more elements the object simply get randomic orders, i really dont know what's going on, if someone could help me i would be grateful.
That's just the way it works with a for in loop and a non-array Object. It's documented on the Adobe website:
The for..in loop iterates through the properties of an object, or the elements of an array. For example, you can use a for..in loop to iterate through the properties of a generic object (object properties are not kept in any particular order, so properties may appear in a seemingly random order).

Resources