Ruby-在一系列哈希中找到最常用的药物名称

时间:2019-02-12 18:54:09

标签: ruby hash

我需要获得哈希表中最常用的药物名称。

数组数据为:

Medicine.create([{name: "Apixibucil", patient_id: 1, review_id: 17, nurse_id: 2},
  {name: "Adriacilin", patient_id: 1, review_id: 17, nurse_id: 12},
  {name: "Tiaferol", patient_id: 4, review_id: 2, nurse_id: 17},
  {name: "Afalinum", patient_id: 6, review_id: 7, nurse_id: 10},
  {name: "Afalinum", patient_id: 9, review_id: 9, nurse_id: 9},
  {name: "Afalinum", patient_id: 22, review_id: 13, nurse_id: 1}])

我写的代码是(该方法是CLI的一部分,这就是为什么要包含它的原因):

def most_common_medicine_on_study
  puts "Do you want to know the most popular medicine in the study?"
  puts ">"
  input = gets.chomp
  if input == "yes" || "y"
    Medicine["data"].each do |meds|
      meds["name"].max_by {|name| name.length}
    end
  end
end

2 个答案:

答案 0 :(得分:3)

使用有效的Ruby数组:

medicine = [{name: "Apixibucil", patient_id: 1, review_id: 17, nurse_id: 2},
            {name: "Adriacilin", patient_id: 1, review_id: 17, nurse_id: 12},
            {name: "Tiaferol", patient_id: 4, review_id: 2, nurse_id: 17},
            {name: "Afalinum", patient_id: 6, review_id: 7, nurse_id: 10},
            {name: "Afalinum", patient_id: 9, review_id: 9, nurse_id: 9},
            {name: "Afalinum", patient_id: 22, review_id: 13, nurse_id: 1}]

您可以使用Enumerable#group_byHash#transform_values

medicine.group_by{ |h| h[:name] }.transform_values { |v| v.size}.max_by { |_, v| v }

或者使用Enumerable#each_with_object使用Hash#new的默认值为0,以进行计数:

medicine.each_with_object(Hash.new(0)) { |h, o| o[h[:name]] += 1 }.max_by { |_, v| v }

两种方法都使用Enumerable#max_by来获取最大计数,并返回:

["Afalinum", 3]


如果您正在使用Rails check calculations,也许可以这样做:

Medicine.group(:name).count
# => { 'Apixibucil' => 1, 'Adriacilin' => 1, 'Tiaferol' => 1, 'Afalinum' => 3 }

答案 1 :(得分:0)

这是一个解决方案。

Medicine['data'].reduce Hash.new(0) do |count, med|
  count[med[:name]] += 1
  count
end.max_by(&:last)

#=> ["Afalinum", 3]

1)减少所有值均默认为0的哈希。

2)计算每个医学名称的出现。

3)从计数器返回最大计数。

标有基准

为了让每个人都了解建议的方法在哪里运行的性能,这里是速度和内存使用情况的输出。为了运行测试,我复制了数据以使其具有约3,000,000个条目。

benchmarker do
  result = data.reduce Hash.new(0) do |count, med|
    count[med[:name]] += 1
    count
  end.max_by(&:last)

  puts result
end
#=> [Afalinum, 1500000]
#=> {"ruby":"2.5.1","elapsed_time":0.72,"garbage_collection":"on","memory_used":"0 MB","garbage_collection_count":1}

benchmarker do
  result = data.each_with_object(Hash.new(0)) { |h, o| o[h[:name]] += 1 }.max_by { |_, v| v }

  puts result
end
#=> [Afalinum, 1500000]
#=> {"ruby":"2.5.1","elapsed_time":0.72,"garbage_collection":"on","memory_used":"0 MB","garbage_collection_count":1}

benchmarker do
  result = data.group_by { |h| h[:name] }.transform_values { |v| v.size}.max_by { |_, v| v }

  puts result
end
#=> [Afalinum, 1500000]
#=> {"ruby":"2.5.1","elapsed_time":0.52,"garbage_collection":"on","memory_used":"18 MB","garbage_collection_count":2}

我发现有趣的是group_by方法实际上可以更快地处理计算,尽管这样做消耗了相当多的内存。第一个在字面上是一样的,由开发人员自行选择,让他们选择更具可读性的方法。