Ger Cas
Ger Cas

Reputation: 2298

How to group array elements by index?

I have the array arr which I want to group by indexes given in array idx. I mean,

With my current code I can group the first sub array with first index of idx idx[0] = 1.

Then, How to replicate for all indexes within array idx? Thanks in advance.

My current code and output is this:

idx = [1,5,7]
arr = ['a','b','c','d','e','f','g','h','i','j','k']

arr.group_by.with_index { |z, i| i <= idx[0] }.values
=> [["a", "b"], ["c", "d", "e", "f", "g", "h", "i", "j", "k"]]

and my desired output is like this:

output   --> [["a", "b"], ["c", "d", "e", "f"], ["g", "h"], ["i", "j", "k"]]

#Indexes -->    0    1      2    3    4    5      6    7      8    9    10  

Upvotes: 5

Views: 1408

Answers (3)

Cary Swoveland
Cary Swoveland

Reputation: 110725

arr = [9, 3, 1, 6, 2, 4, 0, 1, 5, 8] 
end_idx = [1, 5, 7]

[-1, *end_idx, arr.size-1].uniq.each_cons(2).
  map { |s,e| arr.values_at(s+1..e) }
  #=> [[9, 3], [1, 6, 2, 4], [0, 1], [5, 8]]  

The steps are as follow:

a = [-1, *end_idx, arr.size-1]
  #=> [-1, 1, 5, 7, 9]
b = a.uniq
  #=> [-1, 1, 5, 9]
c = b.each_cons(2)
  #=> #<Enumerator: [-1, 1, 5, 7, 9]:each_cons(2)> 
c.map { |s,e| arr.values_at(s+1..e) }
  #=> [[9, 3], [1, 6, 2, 4], [0, 1], [5, 8]] 

One can see the elements generated and passed to map by the enumerator c by converting c to an array.

c.to_a
  #=> [[-1, 1], [1, 5], [5, 7], [7, 9]] 

See Array#values_at.

Upvotes: 1

Stefan
Stefan

Reputation: 114208

You can use slice_after to slice the array after each item whose index is in idx:

idx = [1, 5, 7]
arr = %w[a b c d e f g h i j k]

arr.enum_for(:slice_after).with_index { |_, i| idx.include?(i) }.to_a
#=> [["a", "b"], ["c", "d", "e", "f"], ["g", "h"], ["i", "j", "k"]]

That enum_for is (unfortunately) needed to chain slice_after and with_index.

Upvotes: 6

Dyaniyal Wilson
Dyaniyal Wilson

Reputation: 1060

Another solution

idx = [1, 5, 7]
arr = ['a','b','c','d','e','f','g','h','i','j','k']
from = 0

arr.map.with_index { |a, i|  
  if idx.include?(i)
    result = arr[from..i]  
    from = i + 1 
  end
  result
}.compact

 => [["a", "b"], ["c", "d", "e", "f"], ["g", "h"]] 

Upvotes: 1

Related Questions