ruby - 在哈希中选择某些键
问题描述
我有一个 Hashh
并且想要拥有这些键的数组,其中它们的值满足特定条件。我天真的方法是:
result = h.select { |_, val| val.fulfils_condition? }.keys
这当然可行,但对我来说似乎效率低下,因为它需要构造一个中间哈希,然后从中计算结果数组。
当然我可以做一个显式循环:
result = []
h.each do
|key, val|
result << key if val.fulfils_condition?
end
但是由于对result
. 我也在考虑这个:
result = h.reduce([]) do
|memo, pair|
memo << pair.first if pair.last.fulfils_condition?
memo
end
但这并不是真正更具可读性,并且需要构建中间pair
数组,每个数组都包含一个键值对。
有没有替代的方法,既紧凑,又不需要计算临时哈希?
解决方案
鉴于:
h = {}; (1..100).each {|v| h[v.to_s] = v }
您可以使用 memory_profiler gem 来测量分配。使用类似的东西MemoryProfiler.report { code }.total_allocated
。
如果内存分配在这里真的很重要,那么您预先分配结果然后枚举的#each
方法就是您想要的。这样做的原因是 Ruby优化了 Hash#each 块的数量为 2,因此不会在每个循环中构造一个新数组。这种方法中唯一的分配是结果数组。
MemoryProfiler.report { r = [] ; h.each {|k, v| r << k if v > 1 } }.total_allocated
# => 1
使用#reduce
OTOH 会导致每个循环分配一次,因为您违反了 arity 规则:
MemoryProfiler.report { h.reduce([]) {|agg, (k, v)| agg << k if v > 1 ; agg } }.total_allocated
# => 101
如果您想要更“独立”的东西并且愿意牺牲额外的分配,您将需要使用#each_key
(它确实创建了一个中间键数组)然后索引到哈希中以测试每个值。
h.each_key.select {|k| h[k] > 1 }
推荐阅读
- google-sheets-formula - IMPORTXML 值返回的价格不是数字 - 需要帮助才能转换
- api - Google youtube api 扩展配额
- python-3.x - 如何将两个可能不同的 sqlite3 列表与综合列表进行比较并添加新值?
- reactjs - 下一个 js 从 Json 的特定项目中获取道具
- python - 根据列表重命名列
- python - R 表的 python 等效项(iris$Species)
- c++ - 有没有办法为现代 OpenGL 中的每个键回调设置随机位置?
- java - 在 ElasticSearch 中更新数据
- javascript - 如何使用 web3 创建私钥和公钥?
- sql - 我们可以在 SQL Server 中将用户定义的标量函数调用为内联表值函数吗?