4

I need to split an array into X smaller array. I don't care about the number of elements in the smaller arrays I just need to create X arrays from a larger one. I've been doing some reading and it seems like I need a method similar to the in_groups method from rails. I am not using rails right now, just ruby.

1
  • 1
    You could do this: def doit(a,x) a.each_slice((a.size.to_f/x).ceil.to_i).to_a end. Suppose a = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]. Then doit(a,3) #=> [[1, 2, 3, 4], [5, 6, 7, 8], [9, 10]] doit(a,4) #=> [[1, 2, 3], [4, 5, 6], [7, 8, 9], [10]] doit(a,5) #=> [[1, 2], [3, 4], [5, 6], [7, 8], [9, 10]]. Commented Jan 18, 2015 at 1:39

5 Answers 5

7

Requiring Rails just to get that function is overkill. Just use each_slice:

team = ['alice', 'andy', 'bob', 'barry', 'chloe', 'charlie']
=> ["alice", "andy", "bob", "barry", "chloe", "charlie"]

team.each_slice(2).to_a
=> [["alice", "andy"], ["bob", "barry"], ["chloe", "charlie"]]

each_slice's parameter is the number of elements in each slice (except possibly the last slice). Since you're looking for X slices, you can do something like this:

team.each_slice(team.length/X).to_a

That's not perfect, as you'll get one extra slice if the array length is not a multiple of X, but gets you in the ballpark and you can tweak it from there depending on what exactly your needs are.

Since you say you don't care how many are in each, you could just use the length/x approach above, then check to see if you have one too many slices. If so, just join the last two slices into one jumbo-size slice. This might avoid some fussy math or floating point operations.

Sign up to request clarification or add additional context in comments.

Comments

3

if x is a count of groups:

x = 2
a = [1,2,3,4,5,6,7,8,9,10,11,12]
a.in_groups(x)

=> [[1, 2, 3, 4, 5, 6], [7, 8, 9, 10, 11, 12]]

if group by x pieces:

x = 2
a = [1,2,3,4,5,6,7,8,9,10,11,12]
a.each_slice(x).to_a

=> [[1, 2], [3, 4], [5, 6], [7, 8], [9, 10], [11, 12]]

Comments

2

You can make your own method, here's a basic idea:

class Array
  def my_group(x)
    start = 0
    size = (self.size() / Float(x)).ceil
    while x > 0
      yield self[start, size]
      size = ((self.size() - 1 - start) / Float(x)).ceil
      start += size
      x -= 1
    end
  end
end

%w(1 2 3 4 5 6 7 8 9 10).my_group(3) {|group| p group}
# =>["1", "2", "3", "4"]
# =>["4", "5", "6"]
# =>["7", "8", "9"]

Comments

2

I decided to put:

require 'active_support/core_ext/array/grouping'

2 Comments

Just require 'active_support/core_ext/array/grouping' should be enough. No need to require all core extensions, and certainly not the whole behemoth that is Rails.
Is this to be your selected answer? If not, it's not necessary, nor is it desired that you create an answer just to tell us.
0

If you need to have N groups, you can use the in_groups monkey-patch provided by ActiveSupport, as mentioned in another answer:

require 'active_support/core_ext/array/grouping'
my_array = [1,2,3,4,5]
my_array.in_groups(2)
# => [[1, 2, 3], [4, 5, nil]]
my_array.in_groups(2, false)
# => [[1, 2, 3], [4, 5]]

If you care about the number of elements in the group as opposed to the number of groups, you can use each_slice provided by Ruby core:

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

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.