2015-02-06 242 views
0

我有數組:紅寶石分組元素

a = [1, 3, 1, 3, 2, 1, 2] 

我想GROUP BY值,但將其保存索引,所以結果一定是這個樣子的:

[[0, 2, 5], [1, 3], [4, 6]] 

或哈希

{1=>[0, 2, 5], 3=>[1, 3], 2=>[4, 6]} 

現在我正在使用相當難看又大的代碼:

struc = Struct.new(:index, :value) 
array = array.map.with_index{ |v, i| struc.new(i, v) }.group_by {|s| s[1]}.map { |h| h[1].map { |e| e[0]}} 

`

回答

2

如果你使用一個哈希默認值以避免在元素上迭代兩次:

a = [1, 3, 1, 3, 2, 1, 2] 

Hash.new { |h, k| h[k] = [] }.tap do |result| 
    a.each_with_index { |i, n| result[i] << n } 
end 
#=> { 1 => [0, 2, 5], 3 => [1, 3], 2 => [4, 6] } 
+1

好,或'a.each_with_index.with_object(Hash.new {| h,k | h [k] = []}){|(e,i),h | h [e] << i}'。 – 2015-02-06 23:04:58

+0

謝謝@CarySwoveland:TIL'with_object',從未考慮過此方法。 – spickermann 2015-02-06 23:08:57

+0

你也可以使用[Enumerator#with_index](http://ruby-doc.org/core-2.1.5/Enumerator.html#method-i-with_index):'a.each_with_object(Hash.new {| h, k | h [k] = []})。with_index {|(e,h),i | h [e] << i}'。請注意塊變量的不同順序。 TIL TIL。 – 2015-02-06 23:48:27

2
a = [1, 3, 1, 3, 2, 1, 2] 
a.each_with_index.group_by(&:first).values.map { |h| h.map &:last } 

首先,我們在形式[val, idx], ...each_with_index)得到一個Enumerator,然後group_by的值(在對first值),則取每對的索引(last元素)。