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
Ruby Regular Expression to Match a Url
Difference Between Print and Puts
How to Implement a Short Url Like the Urls in Twitter
Rspec: Expect VS Expect With Block - What's the Difference
Read and Write Yaml Files Without Destroying Anchors and Aliases
Mavericks, Rbenv, Your Ruby Version Is 2.0.0, But Your Gemfile Specified 2.1.1
Setting Up Rake-Pipeline for Use with Handlebars Alongside Google App Engine
Calculating the Number of Weeks in a Year with Ruby
Rails 3. Creating a Production Database
Counter_Cache With Has_Many :Through
How to Count Duplicates in Ruby Arrays
How to Access a Variable Defined in a Ruby File I Required in Irb
Using God to Monitor Unicorn - Start Exited with Non-Zero Code = 1
Is This the Best Way to Unescape Unicode Escape Sequences in Ruby