Need to Split Arrays to Sub Arrays of Specified Size in Ruby

Need to split arrays to sub arrays of specified size in Ruby

arr.each_slice(3).to_a

each_slice returns an Enumerable, so if that's enough for you, you don't need to call to_a.

In 1.8.6 you need to do:

require 'enumerator'
arr.enum_for(:each_slice, 3).to_a

If you just need to iterate, you can simply do:

arr.each_slice(3) do |x,y,z|
puts(x+y+z)
end

Split array of subarrays by subarrays sum size Ruby

You can use reduce method and keep pushing sub arrays to a new array. Consider the following:

new_arr = arr.reduce([]) do |acc, sub_array|
last_element = acc[acc.length - 1]

if last_element.nil? or (last_element + sub_array).length > 6
acc << sub_array
else
acc[acc.length - 1] = last_element + sub_array
end
acc
end

# Tests
new_arr.flatten.size == arr.flatten.size # test total number of elements in both the arrays
new_arr.map(&:size) # the sizes of all sub arrays
new_arr.map(&:size).min # min size of all sub arrays
new_arr.map(&:size).max # max size of all sub arrays

Let me know if the code is not clear to you

Update:

Reduce method will "reduce" any enumerable object to a single value by iterating through every element of the enumerable just like each, map

Consider an example:

# Find the sum of array
arr = [1, 2, 3]

# Reduce will accept an initial value & a block with two arguments
# initial_value: is used to set the value of the accumulator in the first loop

# Block Arguments:
# accumulator: accumulates data through the loop and finally returned by :reduce
# value: each item of the above array in every loop(just like :each)

arr.reduce(0) do |acc, value|
# initial value is 0; in the first loop acc's value will be set to 0
# henceforth acc's value will be what is returned from the block in every loop

acc += value
acc # acc is begin returned; in the second loop the value of acc will be (0 + 1)
end

So in this case in every loop, we add the value of the item to the accumulator and return the accumulator for use in the next loop. And once reduce has iterated all the items in the array it will return the accumulator.

Ruby also provides syntactic sugar to make it look much fancier:

arr.reduce(:+) # return 6

Here's a good article for further reference

So if you take your question for example:

# Initial value is set to an empty array, what we're passing to reduce
new_arr = arr.reduce([]) do |acc, sub_array|
# In the first loop acc's value will be set to []

# we're finding the last element of acc (in first loop since the array is empty
# last element will be nil)
last_element = acc[acc.length - 1]

# If last_element is nil(in first loop) we push the first item of the array to acc
# If last_element is found(pushed in the previous loops), we take it and sum
# it with the item from the current loop and see the size, if size is more
# than 6, we only push the item from current loop
if last_element.nil? or (last_element + sub_array).length > 6
acc << sub_array
else
# If last element is present & last_element + item from current loop's size
# is less than 6, we push the (last_element + item from current loop) into
# the accumulator.
acc[acc.length - 1] = last_element + sub_array
end

# Finally we return the accumulator, which will be used in the next loop
# Or if has looped through the entire array, it will be used to return back
# from where it was called
acc
end

Ruby, is there a built in method to split an array into two sub arrays at a specified index?

There is :)

arr1 = [2, 1, 2, 2, 2].take 2
arr2 = [2, 1, 2, 2, 2].drop 2

How to split a Ruby array into subarrays of unequal size using a delimiter

Enumerable#slice_before does this exact thing:

arr = [0, 1, 1, 2, 3, 1, 0, 0, 1]
p arr.slice_before(0).to_a
# => [[0, 1, 1, 2, 3, 1], [0], [0, 1]]

See it on repl.it: https://repl.it/FBhg

How to split (chunk) a Ruby array into parts of X elements?

Take a look at Enumerable#each_slice:

foo.each_slice(3).to_a
#=> [["1", "2", "3"], ["4", "5", "6"], ["7", "8", "9"], ["10"]]

How do I slice an array in ruby into sub arrays of a specified length?

Try this

a = [1,2,3,4,5,6,7,8,9,10]
slices = [1,2,3,4].map { |n| a.shift(n) }

This slices the array into pieces

NB, this mutates the original array.

Is there a Ruby 1.8.7 built-in to split an array into same sized subarrays?

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

For 1.8.6:

require 'enumerator'
[1,2,3,4,5,6].enum_for(:each_slice, 3).to_a

Ruby Split array in sub arrays that contain only different values

I assume you want to have the minimum number of subarrays.

arr = [20, 20, 21, 21, 21, 21, 22, 23, 22]

h = arr.each_with_object(Hash.new(0)) { |n,h| h[n] += 1 }
#=> {20=>2, 21=>4, 22=>2, 23=>1}
a = Array.new(h.values.max) { Array.new { [] } }
#=> [[], [], [], []]
h.each { |n,freq| freq.times { |i| a[i] << n } }
a #=> [[20, 21, 22, 23], [20, 21, 22], [21], [21]]

h.values.max
#=> 4

tells us we need at least 4 subarrays (for 21). 4 is clearly sufficient as we simply allocate each group of equal elements to different subarrays.

See the form of Hash::new that takes a default value and Array::new.

If h = Hash.new(0), then if h does not have a key k, h[k] returns the default value, here zero. When h[k] += 1 is executed Ruby's first step is to convert that expression to:

h[k] = h[k] + 1

If h does not have a key k the expression h[k] on the right of the equality returns zero.

A variant (after computing h) is the following:

h.each_with_object([]) do |(n,freq),a|
freq.times { |i| i >= a.size ? a << [n] : a[i] << n }
end
#=> [[20, 21, 22, 23], [20, 21, 22], [21], [21]]


Related Topics



Leave a reply



Submit