ruby - 遍历哈希以查找数组中预定义的值
问题描述
我有一个带有哈希的数组:
test = [
{"type"=>1337, "age"=>12, "name"=>"Eric Johnson"},
{"type"=>1338, "age"=>18, "name"=>"John Doe"},
{"type"=>1339, "age"=>22, "name"=>"Carl Adley"},
{"type"=>1340, "age"=>25, "name"=>"Anna Brent"}
]
我有兴趣获取名称键等于可以在数组中找到的值的所有哈希:
get_hash_by_name = ["John Doe","Anna Brent"]
最终结果如下:
# test_sorted = would be:
# {"type"=>1338, "age"=>18, "name"=>"John Doe"}
# {"type"=>1340, "age"=>25, "name"=>"Anna Brent"}
我可能不得不以test.each
某种方式进行迭代,但我仍然试图掌握 Ruby。很高兴所有的帮助!
解决方案
这里有一些东西可以冥想:
遍历数组以查找某些内容很慢,即使它是一个排序数组。计算机语言有各种可以用来提高查找速度的结构,而在 Ruby 中,哈希通常是一个很好的起点。Array 就像从顺序文件中读取,Hash 就像从随机访问文件中读取,我们可以直接跳转到我们需要的记录。
从您test
的哈希数组开始:
test = [
{'type'=>1337, 'age'=>12, 'name'=>'Eric Johnson'},
{'type'=>1338, 'age'=>18, 'name'=>'John Doe'},
{'type'=>1339, 'age'=>22, 'name'=>'Carl Adley'},
{'type'=>1340, 'age'=>25, 'name'=>'Anna Brent'},
{'type'=>1341, 'age'=>13, 'name'=>'Eric Johnson'},
]
请注意,我添加了额外的“Eric Johnson”记录。我稍后再谈。
我会创建一个散列,将散列数组映射到常规散列,其中每对的键是唯一值。'type'
键/值对似乎很适合该需求:
test_by_types = test.map { |h| [
h['type'], h]
}.to_h
# => {1337=>{"type"=>1337, "age"=>12, "name"=>"Eric Johnson"},
# 1338=>{"type"=>1338, "age"=>18, "name"=>"John Doe"},
# 1339=>{"type"=>1339, "age"=>22, "name"=>"Carl Adley"},
# 1340=>{"type"=>1340, "age"=>25, "name"=>"Anna Brent"},
# 1341=>{"type"=>1341, "age"=>13, "name"=>"Eric Johnson"}}
现在test_by_types
是一个散列,使用该type
值指向原始散列。
如果我基于名称创建一个类似的散列,其中每个名称,无论是否唯一,都指向type
值,我可以进行快速查找:
test_by_names = test.each_with_object(
Hash.new { |h, k| h[k] = [] }
) { |e, h|
h[e['name']] << e['type']
}.to_h
# => {"Eric Johnson"=>[1337, 1341],
# "John Doe"=>[1338],
# "Carl Adley"=>[1339],
# "Anna Brent"=>[1340]}
请注意,“Eric Johnson”指向两条记录。
现在,这是我们查找事物的方式:
get_hash_by_name = ['John Doe', 'Anna Brent']
test_by_names.values_at(*get_hash_by_name).flatten
# => [1338, 1340]
在一次快速查找中,Rubytypes
通过查找名称返回了匹配项。
我们可以获取该输出并获取原始哈希值:
test_by_types.values_at(*test_by_names.values_at(*get_hash_by_name).flatten)
# => [{"type"=>1338, "age"=>18, "name"=>"John Doe"},
# {"type"=>1340, "age"=>25, "name"=>"Anna Brent"}]
因为这是针对哈希运行的,所以速度很快。哈希可以很大,它仍然会运行得非常快。
回到“埃里克·约翰逊”……
在处理人名时,可能会出现名称冲突,这就是test_by_names
允许多个type
值的原因,因此只需一次查找即可检索到所有匹配记录:
test_by_names.values_at('Eric Johnson').flatten
# => [1337, 1341]
test_by_types.values_at(*test_by_names.values_at('Eric Johnson').flatten)
# => [{"type"=>1337, "age"=>12, "name"=>"Eric Johnson"},
# {"type"=>1341, "age"=>13, "name"=>"Eric Johnson"}]
如果您是 Ruby 新手,这将有很多需要细细琢磨的内容,但是 Ruby 文档涵盖了所有内容,因此请仔细阅读Hash、Array和Enumerable类文档。
此外,*
又名“splat”,将封闭数组中的数组元素分解为适合传递给方法的单独参数。我不记得那是在哪里记录的。
如果你熟悉数据库设计,这看起来很熟悉,因为它类似于我们进行数据库查找的方式。
所有这一切的重点是,当您第一次将数据摄取到程序中时,考虑如何存储数据非常重要。做错了,你会跳过主要的障碍,试图用它做有用的事情。做对了,代码和数据将非常容易地通过,您将能够轻松地按摩/提取/组合数据。
换句话说,数组是用于保存您想要按顺序访问的东西的容器,例如您想要打印的作业、您需要按顺序访问的站点、您想要按特定顺序删除的文件,但是当您想要时它们很糟糕随机查找和使用记录。
知道哪个容器是合适的很重要,对于这个特定的任务,哈希数组似乎是不合适的,因为没有快速的方法来访问特定的。
这就是为什么我在上面发表评论,询问您首先要完成的工作。有关该特定问题的更多信息,请参阅“什么是 XY 问题? ”和“ XyProblem ”。
推荐阅读
- html - HTML 表格 - 使单列响应
- python - 如何序列化嵌套属性而不显示整个对象?
- javascript - 如何在 Javascript 中从 Firebase 检索数据?
- excel - Visual Basic 如何识别小拉丁字母“č”
- azure - Azure 数据仓库物化视图导致数据库项目 Visual Studio 2019 中出现问题
- python - PyCharm 上的 Selenium 找不到 firefox 二进制文件
- mqtt - mqtt 订阅 IBM Watson IoT
- c# - 使用 RestSharp 调用 API 时出现“invalid_grant”错误
- python - 使用 QPainterPath 在两点之间绘制直线
- bootstrap-4 - 使用 Bootstrap 4,为什么不显示 navbar-icon-bar?