基于ruby中的某些键,对哈希数组的出现进行分组和显示

时间:2017-02-13 14:39:07

标签: arrays ruby hash

我有一系列像这样的哈希:

[
  {"a"=>"first", "b"=>[{"lt"=>7, "lg"=>8}]},
  {"a"=>"first", "b"=>[{"lt"=>7, "lg"=>8}]},
  {"a"=>"second", "b"=>[{"lt"=>7, "lg"=>8}]},
  {"a"=>"third", "b"=>[{"lt"=>9, "lg"=>10}]}
]

如何按"a"键值显示事件并显示类似

的内容
[
  {{"a"=>"first", "b"=>[{"lt"=>7, "lg"=>8}]}=>2},
  {{"a"=>"second", "b"=>[{"lt"=>7, "lg"=>8}]}=>1},
  {{"a"=>"third", "b"=>[{"lt"=>9, "lg"=>10}]}=>1}
]

我正在寻找“红宝石方式”解决方案。

3 个答案:

答案 0 :(得分:4)

frequency_distribution

您可以使用带有哈希的each_with_object和默认出现值Enumerable#frequency_distribution来定义0

module Enumerable
  def frequency_distribution
    each_with_object(Hash.new(0)) { |element, count| count[element] += 1 }
  end
end

它的工作原理如下:

require 'pp'
data = [
    {"a"=>"first", "b"=>[{"lt"=>7, "lg"=>8}]},
    {"a"=>"first", "b"=>[{"lt"=>7, "lg"=>8}]},
    {"a"=>"second", "b"=>[{"lt"=>7, "lg"=>8}]},
    {"a"=>"third", "b"=>[{"lt"=>9, "lg"=>10}]}
]

pp data.frequency_distribution
# {{"a"=>"first", "b"=>[{"lt"=>7, "lg"=>8}]}=>2,
#  {"a"=>"second", "b"=>[{"lt"=>7, "lg"=>8}]}=>1,
#  {"a"=>"third", "b"=>[{"lt"=>9, "lg"=>10}]}=>1}

如果你不想修补Enumerable

def frequency_distribution(array)
  array.each_with_object(Hash.new(0)) { |e, h| h[e] += 1 }
end

frequency_distribution(data)
# {{"a"=>"first", "b"=>[{"lt"=>7, "lg"=>8}]}=>2,
#  {"a"=>"second", "b"=>[{"lt"=>7, "lg"=>8}]}=>1,
#  {"a"=>"third", "b"=>[{"lt"=>9, "lg"=>10}]}=>1}

请注意,输出是一个哈希。键是哈希值,值是整数。我想不出将它转换为1对哈希数组的任何好理由。查找速度会慢得多,而且可读性也会降低。

count_by

对于更通用的方法,您可以使用与Enumerable#count_bygroup_by相同的语法定义sort_by

module Enumerable
  def count_by(&block)
    each_with_object(Hash.new(0)) { |element, count| count[block.call(element)] += 1 }
  end
end

require 'pp'
data = [
    {"a"=>"first", "b"=>[{"lt"=>7, "lg"=>8}]},
    {"a"=>"first", "b"=>[{"lt"=>7, "lg"=>8}]},
    {"a"=>"second", "b"=>[{"lt"=>7, "lg"=>8}]},
    {"a"=>"third", "b"=>[{"lt"=>9, "lg"=>10}]}
]

pp data.count_by(&:itself)
# {{"a"=>"first", "b"=>[{"lt"=>7, "lg"=>8}]}=>2,
#  {"a"=>"second", "b"=>[{"lt"=>7, "lg"=>8}]}=>1,
#  {"a"=>"third", "b"=>[{"lt"=>9, "lg"=>10}]}=>1}

pp data.count_by(&:keys)
#=> {["a", "b"]=>4}

pp data.count_by{|key, value| key["a"]}
#=> {"first"=>2, "second"=>1, "third"=>1}

答案 1 :(得分:2)

{{1}}

答案 2 :(得分:2)

正如我理解的那样,它与给定数组的特定元素无关。更一般地说,给定一个数组

arr = [a,a,b,c] 

其中abc任何 Ruby对象,您需要计算每个唯一元素的数量,表示为哈希数组。为了简单起见,假设

arr = [1,1,2,3]

以下是通过arr进行单次传递来获取计数的两种方法。

arr.group_by(&:itself).map { |k,v| { k=>v.size } }
  #=> [{ 1=>2 }, { 2=>1 }, { 3=>1 }]

和(计算哈希,@ Eric在他的回答中使用)

arr.each_with_object(Hash.new(0)) { |e,h| h[e] += 1 }
  #=> [{ 1=>2 }, { 2=>1 }, { 3=>1 }]