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

  • 本文关键字:数组 项目 Ruby 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"]]

谁能帮忙?

下次,如果您添加一些尝试执行的步骤来获得所需的内容,那就太好了,这是一个快速的解决方案:

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

但是,这会改变原始arr

@Md.法汉记忆有很好的解决方案,没有突变

替代解决方案,不更改原始对象,不需要 dup。

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

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

其他答案已经提供了完美的解决方案。我发布这个是为了展示一个应用程序(鲜为人知? 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"]

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

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"]]

最新更新