按散列中的数组元素分组,计算计数
Group by array element within a hash, calculate counts
我有一个 Ruby 哈希:
example = {
:key1 => [1, 1, 4],
:key2 => [1, 2, 3],
:key3 => [1, 3, 2],
:key4 => [1, 5, 0],
:key5 => [1, 7, 2],
:key6 => [2, 1, 5],
:key7 => [2, 2, 4],
:key8 => [2, 4, 2],
:key9 => [3, 1, 6],
:key10 => [3, 2, 5],
:key11 => [3, 3, 4]
}
如何按值数组中的第一个元素对散列进行分组?一旦分组,我如何计算每个组并将它们存储到一个额外的散列中?
如果我能够提取计数,我愿意跳过 group_by
部分。
示例所需输出:
groups = {:group1 => 5, :group2 => 3, :group3 => 3}
这是一种方法:
example.values.group_by(&:first).each_with_object({}) { |(k,v),h|
h.update("group#{k}".to_sym=>v.size) }
#=> {:group1=>5, :group2=>3, :group3=>3}
步骤:
example = {:key1=> [1, 1, 4], :key2=> [1, 2, 3], :key3=>[1, 3, 2],
:key4=> [1, 5, 0], :key5=> [1, 7, 2], :key6=>[2, 1, 5],
:key7=> [2, 2, 4], :key8=> [2, 4, 2], :key9=>[3, 1, 6],
:key10=>[3, 2, 5], :key11=>[3, 3, 4]}
v = example.values
#=> [[1, 1, 4], [1, 2, 3], [1, 3, 2], [1, 5, 0], [1, 7, 2], [2, 1, 5],
# [2, 2, 4], [2, 4, 2], [3, 1, 6], [3, 2, 5], [3, 3, 4]]
g = v.group_by(&:first) # same as group_by { |k,_| k }
#=> {1=>[[1, 1, 4], [1, 2, 3], [1, 3, 2], [1, 5, 0], [1, 7, 2]],
# 2=>[[2, 1, 5], [2, 2, 4], [2, 4, 2]],
# 3=>[[3, 1, 6], [3, 2, 5], [3, 3, 4]]}
enum = g.each_with_object({})
#=> #<Enumerator: { 1=>[[1, 1, 4], [1, 2, 3], [1, 3, 2], [1, 5, 0], [1, 7, 2]],
# 2=>[[2, 1, 5], [2, 2, 4], [2, 4, 2]],
# 3=>[[3, 1, 6], [3, 2, 5], [3, 3, 4]]
# }:each_with_object({})>
将枚举器转换为数组以检查其值:
enum.to_a
#=> [[[1, [[1, 1, 4], [1, 2, 3], [1, 3, 2], [1, 5, 0], [1, 7, 2]]], {}],
# [[2, [[2, 1, 5], [2, 2, 4], [2, 4, 2]]], {}],
# [[3, [[3, 1, 6], [3, 2, 5], [3, 3, 4]]], {}]]
注意散列值,目前为空。将 enum
的第一个元素传递给块:
(k,v),h = enum.next
#=> [[1, [[1, 1, 4], [1, 2, 3], [1, 3, 2], [1, 5, 0], [1, 7, 2]]], {}]
k #=> 1
v #=> [[1, 1, 4], [1, 2, 3], [1, 3, 2], [1, 5, 0], [1, 7, 2]]
h #=> {}
h.update("group#{k}".to_sym=>v.size)
#=> {}.update(:group1=>5)
#=> {:group1=>5} (new value of h)
如果我们现在检查 enum
的元素,我们会看到哈希值已更新:
enum.to_a
#=> [[[1, [[1, 1, 4], [1, 2, 3], [1, 3, 2], [1, 5, 0], [1, 7, 2]]],
# {:group1=>5}],
# [[2, [[2, 1, 5], [2, 2, 4], [2, 4, 2]]], {:group1=>5}],
# [[3, [[3, 1, 6], [3, 2, 5], [3, 3, 4]]], {:group1=>5}]]
继续...
(k,v),h = enum.next
#=> [[2, [[2, 1, 5], [2, 2, 4], [2, 4, 2]]], {:group1=>5}]
k #=> 2
v #=> [[2, 1, 5], [2, 2, 4], [2, 4, 2]]
h #=> {:group1=>5}
h.update("group#{k}".to_sym=>v.size)
#=> {:group1=>5, :group2=>3}
(k,v),h = enum.next
#=> [[3, [[3, 1, 6], [3, 2, 5], [3, 3, 4]]], {:group1=>5, :group2=>3}]
h.update("group#{k}".to_sym=>v.size)
#=> {:group1=>5, :group2=>3, :group3=>3}
这是使用 each_with_object
的方法:
example.each_with_object(Hash.new(0)) { |(_, (v, *)), h| h[:"group#{v}"] += 1 }
# => {:group1=>5, :group2=>3, :group3=>3}
或者像这样更清楚:
arrays_by_first_element = example.values.group_by { |a| a[0] }
groups = {}
arrays_by_first_element.each { |k, v| groups[k] = v.size }
简单的一行:
puts example.map{|k,v| v[0]}.inject(Hash.new(0)) { |total, e| total[("group%s" % e)] += 1; total}
输出:
{"group1"=>5, "group2"=>3, "group3"=>3}
这是 "easy" 版本的一个(数组 w/o 键):
example.group_by { |k, v| v.first }.values.map(&:count)
我有一个 Ruby 哈希:
example = {
:key1 => [1, 1, 4],
:key2 => [1, 2, 3],
:key3 => [1, 3, 2],
:key4 => [1, 5, 0],
:key5 => [1, 7, 2],
:key6 => [2, 1, 5],
:key7 => [2, 2, 4],
:key8 => [2, 4, 2],
:key9 => [3, 1, 6],
:key10 => [3, 2, 5],
:key11 => [3, 3, 4]
}
如何按值数组中的第一个元素对散列进行分组?一旦分组,我如何计算每个组并将它们存储到一个额外的散列中?
如果我能够提取计数,我愿意跳过 group_by
部分。
示例所需输出:
groups = {:group1 => 5, :group2 => 3, :group3 => 3}
这是一种方法:
example.values.group_by(&:first).each_with_object({}) { |(k,v),h|
h.update("group#{k}".to_sym=>v.size) }
#=> {:group1=>5, :group2=>3, :group3=>3}
步骤:
example = {:key1=> [1, 1, 4], :key2=> [1, 2, 3], :key3=>[1, 3, 2],
:key4=> [1, 5, 0], :key5=> [1, 7, 2], :key6=>[2, 1, 5],
:key7=> [2, 2, 4], :key8=> [2, 4, 2], :key9=>[3, 1, 6],
:key10=>[3, 2, 5], :key11=>[3, 3, 4]}
v = example.values
#=> [[1, 1, 4], [1, 2, 3], [1, 3, 2], [1, 5, 0], [1, 7, 2], [2, 1, 5],
# [2, 2, 4], [2, 4, 2], [3, 1, 6], [3, 2, 5], [3, 3, 4]]
g = v.group_by(&:first) # same as group_by { |k,_| k }
#=> {1=>[[1, 1, 4], [1, 2, 3], [1, 3, 2], [1, 5, 0], [1, 7, 2]],
# 2=>[[2, 1, 5], [2, 2, 4], [2, 4, 2]],
# 3=>[[3, 1, 6], [3, 2, 5], [3, 3, 4]]}
enum = g.each_with_object({})
#=> #<Enumerator: { 1=>[[1, 1, 4], [1, 2, 3], [1, 3, 2], [1, 5, 0], [1, 7, 2]],
# 2=>[[2, 1, 5], [2, 2, 4], [2, 4, 2]],
# 3=>[[3, 1, 6], [3, 2, 5], [3, 3, 4]]
# }:each_with_object({})>
将枚举器转换为数组以检查其值:
enum.to_a
#=> [[[1, [[1, 1, 4], [1, 2, 3], [1, 3, 2], [1, 5, 0], [1, 7, 2]]], {}],
# [[2, [[2, 1, 5], [2, 2, 4], [2, 4, 2]]], {}],
# [[3, [[3, 1, 6], [3, 2, 5], [3, 3, 4]]], {}]]
注意散列值,目前为空。将 enum
的第一个元素传递给块:
(k,v),h = enum.next
#=> [[1, [[1, 1, 4], [1, 2, 3], [1, 3, 2], [1, 5, 0], [1, 7, 2]]], {}]
k #=> 1
v #=> [[1, 1, 4], [1, 2, 3], [1, 3, 2], [1, 5, 0], [1, 7, 2]]
h #=> {}
h.update("group#{k}".to_sym=>v.size)
#=> {}.update(:group1=>5)
#=> {:group1=>5} (new value of h)
如果我们现在检查 enum
的元素,我们会看到哈希值已更新:
enum.to_a
#=> [[[1, [[1, 1, 4], [1, 2, 3], [1, 3, 2], [1, 5, 0], [1, 7, 2]]],
# {:group1=>5}],
# [[2, [[2, 1, 5], [2, 2, 4], [2, 4, 2]]], {:group1=>5}],
# [[3, [[3, 1, 6], [3, 2, 5], [3, 3, 4]]], {:group1=>5}]]
继续...
(k,v),h = enum.next
#=> [[2, [[2, 1, 5], [2, 2, 4], [2, 4, 2]]], {:group1=>5}]
k #=> 2
v #=> [[2, 1, 5], [2, 2, 4], [2, 4, 2]]
h #=> {:group1=>5}
h.update("group#{k}".to_sym=>v.size)
#=> {:group1=>5, :group2=>3}
(k,v),h = enum.next
#=> [[3, [[3, 1, 6], [3, 2, 5], [3, 3, 4]]], {:group1=>5, :group2=>3}]
h.update("group#{k}".to_sym=>v.size)
#=> {:group1=>5, :group2=>3, :group3=>3}
这是使用 each_with_object
的方法:
example.each_with_object(Hash.new(0)) { |(_, (v, *)), h| h[:"group#{v}"] += 1 }
# => {:group1=>5, :group2=>3, :group3=>3}
或者像这样更清楚:
arrays_by_first_element = example.values.group_by { |a| a[0] }
groups = {}
arrays_by_first_element.each { |k, v| groups[k] = v.size }
简单的一行:
puts example.map{|k,v| v[0]}.inject(Hash.new(0)) { |total, e| total[("group%s" % e)] += 1; total}
输出:
{"group1"=>5, "group2"=>3, "group3"=>3}
这是 "easy" 版本的一个(数组 w/o 键):
example.group_by { |k, v| v.first }.values.map(&:count)