"name1", "priority"=>"1", "owner"=>"test3"}, -6ren">
gpt4 book ai didi

ruby - 计算哈希中的多个字段

转载 作者:太空宇宙 更新时间:2023-11-03 16:01:39 25 4
gpt4 key购买 nike

问题:我需要提取某些键并将它们计算在哈希中,作为示例考虑:

data = [{"name"=>"name1", "priority"=>"1", "owner"=>"test3"}, 
{"name"=>"name1", "priority"=>"1", "owner"=>"test4"},
{"name"=>"name2", "priority"=>"1", "owner"=>"test5"},
{"name"=>"name2", "priority"=>"2", "owner"=>"test5"},
{"name"=>"nae954me2", "priority"=>"2", "owner"=>"test5"}]

我想计算每个[id(从名称中提取)和优先级]的记录数,这样最后我会得到类似的东西:

#{{"priority"=>"1", "id"=>"name1"}=>2, {"priority"=>"1", "id"=>"name2"}=>1, {"priority"=>"2", "id"=>"name2"}=>1}

我正在执行以下操作,但我觉得我过于复杂了:

#!/usr/bin/env ruby

data = [{"name"=>"name1", "priority"=>"1", "owner"=>"test3"},
{"name"=>"name1", "priority"=>"1", "owner"=>"test4"},
{"name"=>"name2", "priority"=>"1", "owner"=>"test5"},
{"name"=>"name2", "priority"=>"2", "owner"=>"test5"},
{"name"=>"nae954me2", "priority"=>"2", "owner"=>"test5"}]

# (1) trash some keys, just because I don't need them
data.each do |d|
d.delete 'owner'
# in the real data I have about 4 or 5 that I'm trashing
d['id'] = d['name'].scan(/[a-z][a-z][a-z][a-z][0-9]/)[0] # only valid ids
d.delete 'name'
end

puts data
#output:
#{"priority"=>"1", "id"=>"name1"}
#{"priority"=>"1", "id"=>"name1"}
#{"priority"=>"1", "id"=>"name2"}
#{"priority"=>"2", "id"=>"name2"}
#{"priority"=>"2", "id"=>nil}

# (2) reject invalid keys
data = data.reject { |d| d['id'].nil? }

puts data
#output:
#{"priority"=>"1", "id"=>"name1"}
#{"priority"=>"1", "id"=>"name1"}
#{"priority"=>"1", "id"=>"name2"}
#{"priority"=>"2", "id"=>"name2"}

# (3) count
counts = Hash.new(0)
data.each do |d|
counts[d] += 1
end

puts counts
#{{"priority"=>"1", "id"=>"name1"}=>2, {"priority"=>"1", "id"=>"name2"}=>1, {"priority"=>"2", "id"=>"name2"}=>1}

对改进我的计数方法有什么建议吗?

最佳答案

有很多方法可以做到这一点。 (您可能已经注意到,我对我的答案做了很多编辑,详细解释了一种方法的工作原理,只是为了意识到有更好的方法来做到这一点,所以大砍刀就出来了。)这里有两个解决方案。第一个灵感来自于您采用的方法,但我已尝试将其打包为更像 Ruby。我不确定什么是有效的“名称”,因此我将确定放在一个可以轻松更改的单独方法中。

代码

def name_valid?(name)
name[0..3] == "name"
end

data.each_with_object(Hash.new(0)) {|h,g|
(g[{"id"=>h["name"],"priority"=>h["priority"]}]+=1) if name_valid?(h["name"])}
#=> {{"id"=>"name1", "priority"=>"1"}=>2,
# {"id"=>"name2", "priority"=>"1"}=>1,
# {"id"=>"name2", "priority"=>"2"}=>1}

解释

Enumerable#each_with_object 创建一个初始为空的散列,默认值为零,由 block 变量 g 表示。 g 是通过添加从 data 的元素创建的散列元素构建的:

g[{"id"=>h["name"],"priority"=>h["priority"]}]+=1

如果散列 g 有 key

{"id"=>h["name"],"priority"=>h["priority"]}

与键关联的值加一。如果h没有这个key,

g[{"id"=>h["name"],"priority"=>h["priority"]}]

之前设置为零

g[{"id"=>h["name"],"priority"=>h["priority"]}]+=1

被调用,所以值变为1

替代方法

代码

data.each_with_object({}) do |h,g|
hash = { { "id"=>h["name"], "priority"=>h["priority"] } => 1 }
g.update(hash) { |k, vg, _| vg + 1 } if name_valid?(h["name"])
end
#=> {{"id"=>"name1", "priority"=>"1"}=>2,
# {"id"=>"name2", "priority"=>"1"}=>1,
# {"id"=>"name2", "priority"=>"2"}=>1}

解释

在这里,我使用了 Hash#update (又名 Hash#merge!)将 data(散列)的每个元素合并到初始为空的散列 h(提供的值“名称” 有效)。 更新的 block

{ |k, vg, _| vg + 1 }

当且仅当合并哈希 (g) 和合并哈希 (hash) 具有相同的键 k 时被调用,在这种情况下, block 返回键的值。请注意,第三个 block 变量是散列 hash 的键 k 的值。由于我们不使用该值,因此我将其替换为占位符 _

关于ruby - 计算哈希中的多个字段,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/23642672/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com