Split array up into n-groups of m size? [duplicate] - ruby

This question already has answers here:
Closed 11 years ago.
Possible Duplicate:
Need to split arrays to sub arrays of specified size in Ruby
I'm looking to take an array---say [0,5,3,8,21,7,2] for example---and produce an array of arrays, split every so many places. If the above array were set to a, then
a.split_every(3)
would return [[0,5,3],[8,21,7][2]]
Does this exist, or do I have to implement it myself?

Use Enumerable#each_slice.
a.each_slice(3).to_a
Or, to iterate (and not bother with keeping the array):
a.each_slice(3) do |x,y,z|
p [x,y,z]
end

a = (1..6).to_a
a.each_slice(2).to_a # => [[1, 2], [3, 4], [5, 6]]
a.each_slice(3).to_a # => [[1, 2, 3], [4, 5, 6]]
a.each_slice(4).to_a # => [[1, 2, 3, 4], [5, 6]]

Related

Inserting elements into new array and then deleting from old array, some elements getting ignored

I'm trying to remove pairs of the smallest and largest elements from an Array and store them in a second one. Is there a better way to do this or a Ruby method I don't know about that could accomplish something like this?
Here's my code:
nums = [1, 2, 3, 4, 5, 6]
pairs = []; for n in nums
pairs << [n, nums.last]
nums.delete nums.last
nums.delete n
end
Current result:
nums
#=> [2, 4]
pairs
#=> [[1, 6], [3, 5]]
Expected result:
nums
#=> []
pairs
#=> [[1, 6], [2, 5], [3, 4]]
Assuming nums is sorted and can be modified, I like this way because it has a mechanical feel about it:
pairs = (nums.size/2).times.map { [nums.shift, nums.pop] }
#=> [[1, 6], [2, 5], [3, 4]]
nums
#=> []
I see #Drenmi has the same idea of using shift and pop.
If you don't want to modify nums, you could of course operate on a copy.
Enumerating over an Array while deleting it's content is generally not advisible. Here's an alternative solution:
nums = *(1..6)
#=> [1, 2, 3, 4, 5, 6]
pairs = []
#=> []
until nums.size < 2 do
pairs << [nums.shift, nums.pop]
end
pairs
#=> [[1, 6], [2, 5], [3, 4]]

Array elements are corrupted by lazyness

Why do we see such difference below? Why exactly such array?
enum = [1,2].lazy.flat_map{[[3,4],[5,6]]}.with_index
enum.to_a.map(&:first)
# => [[3, 4], [5, 6], [3, 4], [5, 6]]
enum.map(&:first).to_a
# => [[], [5], [3, 4], [5, 6]]
The reason this happens has nothing to do with lazy - it has something to do with the subtleties of map(&:...).
The first option (enum.to_a.map(&:first)) translates to:
enum.to_a.map { |x| x.first }
# => [[3, 4], [5, 6], [3, 4], [5, 6]]
when x is [[3,4], 0], then [[5,6], 1]...
The second option, one the other hand translates to:
enum.map { |x, i| x.first(i) }
# => [[], [5], [3, 4], [5, 6]]
which brings the first i item for each x array (since the arrays in our example have only 2 elements, x.first(3) still returns two elements...).
The same would happen without lazy:
enum2 = [1,2].flat_map{[[3,4],[5,6]]}.to_enum.with_index
What to_a does in this case is takes the two parameters of each item in the enumeration, and turns them to a single array item.

Ruby coding: Sequence of number pairs "x,y" such that x ranges from 0 to 3 and y from 5 to 7

I am stuck on this problem. I tried to solve it with Ruby.
My answer is
4.times{|i| puts "#{i}"} && 5.upon(7){|i| puts "#{i}}
but, I am not sure that it is correct or not.
This should work for you
result = (0..3).to_a.product((5..7).to_a)
puts result.inspect
#=> [[0, 5], [0, 6], [0, 7], [1, 5], [1, 6], [1, 7], [2, 5], [2, 6], [2, 7], [3, 5], [3, 6], [3, 7]]
not sure that it is correct or not
Generally, in such a case, you try to run the code. Had you done so, you would have noticed (incrementally) that you have a quote missing, that there is no such method as Fixnum#upon (upto would have done it), that the code only outputs a single digit at a time and never a pair, and that the second loop does not run (since times returns nil, and nil && x gets short-circuited so that x does not evaluate).
As to your question, it asks for the sequence of number pairs, and not for its display, so puts is not needed. Also, since you need pairs, you should have the two loops nested, not one after another.
(0..3).flat_map { |x| (4..7).map { |y| [x, y] } }
would be one easy way to write it.
EDIT: flat_map is cooler than map.flatten. Still, macek's answer is more specific +1.

Split an array into some sub-arrays [duplicate]

This question already has answers here:
Closed 11 years ago.
Possible Duplicate:
How to split (chunk) a Ruby array into parts of X elements?
I would like to split an array into an array of sub-arrays.
For example,
big_array = (0...6).to_a
How can we cut this big array into an array of arrays (of a max length of 2 items) such as:
arrays = big_array.split_please(2)
Where...
arrays # => [ [0, 1],
[2, 3],
[4, 5] ]
Note:
I ask this question, 'cause in order to do it, I'm currently coding like this:
arrays = [
big_array[0..1],
big_array[2..3],
big_array[4..5]
]
...which is so ugly. And very unmaintainable code, when big_array.length > 100.
You can use the #each_slice method on the array
big_array = (0..20).to_a
array = big_array.each_slice(2).to_a
puts array # [[0, 1], [2, 3], [4, 5], [6, 7], [8, 9], [10, 11], [12, 13], [14, 15], [16, 17], [18, 19], [20]]
check out the slice:
big_array.each_slice( 2 ).to_a

Subract values of 2 arrays and get a new array with subtracted values

Basically, I want to do this:
[1,2,3,4,5].some_method([1,5,8,7,8])
=> [0,-3,-5,-3,-3]
What is the best way to do this in Ruby?
[1,2,3,4,5].zip([1,5,8,7,8]).map { |a, b| a - b }
p [1,2,3,4,5].zip([1,5,8,7,8]).map{|el| el.first-el.last}
#=> [0, -3, -5, -3, -3]
.zip combines both arrays like [[1, 1], [2, 5], [3, 8], [4, 7], [5, 8]]. With .map there isnt much work left for the block - just subtract the 2 values.
[1,2,3,4,5].zip([1,5,8,7,8]).map{|x|x[0]-x[-1]}
or the usual array iteration
0.upto(a.size-1).map{|x| a[x]-b[x] }

Resources