I have two arrays:
a = [7, 1, 65, 4, 13, 97]
b = []
and I'm trying to append the #divmod return values of each of a
's elements into b
, via the following code:
b << a.map(&4.method(:divmod))
I was expecting the results to be:
b = [[1, 3], [0, 1], [16, 1], [1, 0], [3, 1], [24, 1]]
But instead I get:
b = [[[0, 4], [4, 0], [0, 4], [1, 0], [0, 4], [0, 4]]]
And I don't understand why. Can anyone explain what I'm not understanding?
(I'm having to use &:
because I need to use this code as a method block argument.)
There are two problems with the result you are getting:
To fix (1) you have to assign the result from map
instead of appending the result, i.e.
b = a.map(...)
Regarding (2), your code is equivalent to:
a.map { |n| 4.divmod(n) }
#=> [[0, 4], [4, 0], [0, 4], [1, 0], [0, 4], [0, 4]]
whereas you want: (note that n
and 4
are swapped now)
a.map { |n| n.divmod(4) }
#=> [[1, 3], [0, 1], [16, 1], [1, 0], [3, 1], [24, 1]]
I'm having to use
&:
because I need to use this code as a method argument
I'm not sure what you mean by that, but if you don't want to have an explicit block argument, you can pass a proc or lambda with &
instead:
divmod4 = ->(n) { n.divmod(4) }
b = a.map(&divmod4)
#=> [[1, 3], [0, 1], [16, 1], [1, 0], [3, 1], [24, 1]]
However, since &divmod4
will convert the proc to a block argument, the above is equivalent to calling a.map { |n| n.divmod(4) }
directly. You would only need this approach if you want to re-use that proc, e.g. for passing it to different methods.