我有这些数据:
input = [ [ 'abc', '1.1' ], [ 'abc', '1.2' ], [ 'xyz', '3.14' ] ]
我想输出如下:
[ { 'abc' => [ '1.1', '1.2' ] }, { 'xyz' => '3.14' } ]
是否有可能在一个链表达式中实现这一目标?
答案 0 :(得分:1)
我会这样做:
input = [['abc', '1.1'], ['abc','1.2'], ['xyz', '3.14']]
output = input.each_with_object(Hash.new{ |h, k| h[k] = [] }) { |(k, v), h| h[k] << v }
output # => {"abc"=>["1.1", "1.2"], "xyz"=>["3.14"]}
替代方案不是那么简单:
input.group_by{ |k,v| k }.map{ |k, v| [k, v.map(&:last)] }.to_h # => {"abc"=>["1.1", "1.2"], "xyz"=>["3.14"]}
您的输出结构
output: [{'abc' => ['1.1', '1.2']}, {'xyz' => '3.14'}]
使用哈希是一种非常糟糕的方式。相反,你应该有一个带有多个元素的哈希,因为你将like-key的值组合成一个键。
如果真的需要输出,就像有些人想的那样,那么只需在返回的值上添加map
:
input.each_with_object(Hash.new{ |h, k| h[k] = [] }) { |(k, v), h| h[k] << v }.map{ |k, v| {k => v} }
# => [{"abc"=>["1.1", "1.2"]}, {"xyz"=>["3.14"]}]
答案 1 :(得分:0)
我能想到的最简单的方法:
input.group_by {|x| x[0]}.each_pair.map { |k, v| {k => (a=v.map(&:last)).count > 1 ? a : a[0]} }
答案 2 :(得分:0)
最简单的方法就是这样:
def convert_marray_to_hash(input)
hash = Hash.new { |hash, key| hash[key] = [] }
output = []
input.each { |array| hash[array[0]] << array[1] }
hash.keys.each { |key| output << { key => hash[key] } }
output
end
有很多方法可以做到这一点,但这种方式很好地呈现并且可读。
答案 3 :(得分:0)
这非常有效:
input = [ [ 'abc', '1.1' ], [ 'abc','1.2' ], [ 'xyz', '3.14' ] ]
input.each_with_object({}) do |(key, val), hsh|
hsh[key] = val and next unless hsh.key?(key)
hsh[key] = [ *hsh[key], val ]
end
.map {|key, val| { key => val } }
# => [ { "abc" => [ "1.1", "1.2" ] },
# { "xyz" => "3.14" }
# ]
如果省略最后的map
,你最终会得到一个哈希,这似乎是一个更自然的结果,但这与指定的输出相匹配,至少。