Split an array into some sub-arrays [duplicate] - ruby

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

Related

Convert a nested array to a matrix in Ruby?

When converting a nested array to a matrix in Ruby, the matrix ends up with an extra [] around the values, compared to simply creating a matrix from scratch.
> require 'matrix'
> matrix1 = Matrix[[1,2,3],[4,5,6],[7,8,9]]
> p matrix1
=> Matrix[[1, 2, 3], [4, 5, 6], [7, 8, 9]]
> nested_array = [[1,2,3],[4,5,6],[7,8,9]]
> matrix2 = Matrix[nested_array]
> p matrix2
=> Matrix[[[1, 2, 3], [4, 5, 6], [7, 8, 9]]]
Is there a way to avoid the extra square brackets when building from an array?
matrix2 = Matrix[*nested_array]
p matrix2
=> Matrix[[1, 2, 3], [4, 5, 6], [7, 8, 9]]
The asterisk (*) there is called the "splat operator," and it essentially can be used to treat an array (nested_array in this case) as if it weren't an array, but rather as if its elements were individual elements/arguments.

How to access a nested element, passing array with coordinates

Is there any short way to access an element of a nested array, passing the array with coordinates? I mean something like:
matrix = [[1,2,3,4],[5,6,7,8]]
array = [1,1]
matrix [array]
# => 6
I just wonder if there is a shorter version than:
matrix [array[0]][array[1]]
I believe you want to use the Matrix class:
require 'matrix'
arr = [[1,2,3,4],[5,6,7,8]]
matrix = Matrix[*arr] #=> Matrix[[1, 2, 3, 4], [5, 6, 7, 8]]
matrix[1,1] #=> 6
matrix.row(1) #=> Vector[5, 6, 7, 8]
c = matrix.column(1) #=> Vector[2, 6]
c.to_a #=> [2, 6]
m = matrix.transpose #=> Matrix[[1, 5], [2, 6], [3, 7], [4, 8]]
m.to_a #=> [[1, 5], [2, 6], [3, 7], [4, 8]]
array.inject(matrix, :fetch)
# => 6
matrix[1][1]
should equal 6. matrix[1] is the 2nd array, matrix[1][1] is the second element in that array.

Sum arrays by index using functional programming

I have several equally sized arrays containing numbers (matrix), and I want to sum them all by their index (matrix columns).
For example, if I have:
data = [[1, 2, 3, 4], [5, 6, 7, 8]]
I want to get the result:
column_totals = [6, 8, 10, 12]
I understand how to do this imperatively, but how would I do this using functional programming? (Preferably, using built in Enumerable methods.) I wasn't very happy with any of the functional solutions I came up with.
I ended up using the Matrix class:
require 'matrix'
data = [[1, 2, 3, 4], [5, 6, 7, 8]]
matrix = Matrix[*data]
# Added sum method to Vector class.
matrix.column_vectors.map { |column| column.sum }
I'm happy enough with that solution, but am frustrated that I couldn't wrap my mind around a good functional solution without relying on the Matrix class.
Specifically, I was tripped up on the step to transform this:
data = [[1, 2, 3, 4], [5, 6, 7, 8]]
into this:
columns = [[1, 5], [2, 6], [3, 7], [4, 8]]
Any reason to not use Array#transpose?
data.transpose
# => [[1, 5], [2, 6], [3, 7], [4, 8]]
Alternatively, if you only want to use Enumerable methods to iterate, you can do
columns = data.inject(Array.new(data.first.length){[]}) { |matrix,row|
row.each_with_index { |e,i| matrix[i] << e }
matrix }
# => [[1, 5], [2, 6], [3, 7], [4, 8]]
or
columns = data.flatten.group_by.with_index { |e,i| i % data[0].size }.values
# => [[1, 5], [2, 6], [3, 7], [4, 8]]
To sum:
columns.map { |row| row.inject :+ }
# => [6, 8, 10, 12]
Thirdly, if you don't need the intermediate columns:
data.inject { |s,r| s.zip(r).map { |p| p.inject :+ } }
# => [6, 8, 10, 12]
You could use Array#transpose, as #Matt hinted, and then sum the arrays inside:
data.transpose.map {|a| a.reduce(:+) }

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

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]]

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