通过相同的项目Ruby对数组中的子数组进行分组

时间:2017-06-30 10:10:20

标签: arrays ruby

我有一个数组

arr = [["cat", "15"], ["dog", "17"], ["cat", "20"], ["cat", "356"], ["dog", "89"], ["bird", "65"], ["dog", "336"], ["bird", "545"]]

我想通过相同的第一项对子阵列进行分组,我只需要得到类似的东西:

arr = [["cat", "15", "20", "356"], ["dog", "17", "89", "336"], ["bird", "65","545"]]

有人可以帮忙吗?

4 个答案:

答案 0 :(得分:2)

下次如果你想添加一些你试图获得你想要的步骤会很棒,这是一个快速的解决方案:

> arr.group_by(&:shift).map(&:flatten)
#=> [["cat", "15", "20", "356"], ["dog", "17", "89", "336"], ["bird", "65", "545"]]

但是,这会改变原始的arr

@ Md.FarhanMemon没有mutate的好解决方案

答案 1 :(得分:2)

备用解决方案,不会更改原始对象,不需要复制..

arr.group_by(&:first).map{ |k, v| [k] + v.map { |e| e[1] } }
#=> [["cat", "15", "20", "356"], ["dog", "17", "89", "336"], ["bird", "65", "545"]]

OR

arr.group_by(&:first).map{ |k, v| [k] + v.map(&:last) }
#=> [["cat", "15", "20", "356"], ["dog", "17", "89", "336"], ["bird", "65", "545"]]

答案 2 :(得分:2)

其他答案已经提供了非常好的解决方案。我发布这个是为了显示(鲜为人知的?)assoc方法的应用程序。它使用给定的第一个元素扫描数组中的子数组,几乎就像数组是一个哈希一样。这可用于填充结果array

result = []
arr.each do |name, value|
  group = result.assoc(name)
  if group
    group << value
  else
    result << [name, value]
  end
end

result
#=> [["cat", "15", "20", "356"], ["dog", "17", "89", "336"], ["bird", "65", "545"]]

代码可以进一步缩短为:

arr.each_with_object([]) do |(name, value), result|
  group = result.assoc(name)
  group ? group << value : result << [name, value]
end
#=> [["cat", "15", "20", "356"], ["dog", "17", "89", "336"], ["bird", "65", "545"]]

assoc也可用于从result数组轻松检索特定“密钥”的值:

name, *values = result.assoc('cat')
name   #=> "cat"
values #=> ["15", "20", "356"]

答案 3 :(得分:1)

另一种方法是在hash中添加所有值:

animals = arr.each_with_object(Hash.new{|h, k| h[k] = []}) do |(animal_name, value), obj|
  obj[animal_name] << value
end
#=> {"cat"=>["15", "20", "356"], "dog"=>["17", "89", "336"], "bird"=>["65", "545"]}

然后将其转换为预期输出:

animals.map(&:flatten)
#=> [["cat", "15", "20", "356"], ["dog", "17", "89", "336"], ["bird", "65", "545"]]