我有一个数组
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"]]
有人可以帮忙吗?
答案 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"]]