["author B", "author C"], "Book X"=>["author A", "aut-6ren">
gpt4 book ai didi

Ruby - 如何用数组值反转哈希?

转载 作者:行者123 更新时间:2023-12-01 22:33:02 25 4
gpt4 key购买 nike

寻找适用于 Ruby 1.8.7 的答案:

例如,假设我有这样的哈希:

{"Book Y"=>["author B", "author C"], "Book X"=>["author A", "author B", "author C"]}

我想得到这个:

{ 
"author A" => ["Book X"],
"author B" => ["Book Y", "Book X"],
"author C" => ["Book Y", "Book X"]
}

我为它写了一个很长的方法,但是对于大型数据集,它非常慢。

有什么优雅的解决方案吗?

最佳答案

这是一种方式:

g = {"Book Y"=>["author B", "author C"],
"Book X"=>["author A", "author B", "author C"]}

g.each_with_object({}) do |(book,authors),h|
authors.each { |author| (h[author] ||= []) << book }
end
#=> {"author B"=>["Book Y", "Book X"],
# "author C"=>["Book Y", "Book X"],
# "author A"=>["Book X"]}

步骤:

enum = g.each_with_object({})
#=> #<Enumerator: {"Book Y"=>["author B", "author C"],
# "Book X"=>["author A", "author B", "author C"]}:each_with_object({})>

我们可以看到 enum 的元素,它将通过将其转换为数组来传递到 block 中:

enum.to_a
#=> [[["Book Y", ["author B", "author C"]], {}],
# [["Book X", ["author A", "author B", "author C"]], {}]]

传递给 block 并分配给 block 变量的枚举的第一个元素是:

(book,authors),h = enum.next
#=> [["Book Y", ["author B", "author C"]], {}]
book
#=> "Book Y"
authors
#=> ["author B", "author C"]
h
#=> {}

enum1 = authors.each
#=> #<Enumerator: ["author B", "author C"]:each>
author = enum1.next
#=> "author B"
(h[author] ||= []) << book
#=> (h["author B"] ||= []) << "Book Y"
#=> (h["author B"] = h["author B"] || []) << "Book Y"
#=> (h["author B"] = nil || []) << "Book Y"
#=> h["author B"] = ["Book Y"]
#=> ["Book Y"]
h #=> {"author B"=>["Book Y"]}

下一步:

author = enum1.next
#=> "author C"
(h[author] ||= []) << book
h #=> {"author B"=>["Book Y", "Book Y"], "author C"=>["Book Y"]}

读完“Book X”

(book,authors),h = enum.next
#=> [["Book X", ["author A", "author B", "author C"]],
# {"author B"=>["Book Y", "Book Y"], "author C"=>["Book Y"]}]
book
#=> "Book X"
authors
#=> ["author A", "author B", "author C"]
h
#=> {"author B"=>["Book Y", "Book Y"], "author C"=>["Book Y"]}

我们现在重复与 “Book X” 相同的计算。唯一的区别是当我们遇到:

(h[author] ||= []) << book

相当于

(h[author] = h[author] || []) << book

在大多数情况下,等号右边的h[author]不会是nil(例如,它可能是["Book X"] ,在这种情况下,上述表达式将简化为:

h[author] << book

附录

对于战前的 Ruby 版本(例如 1.8.7),只需先初始化散列并使用 each 而不是 each_with_object (我们在 1.9 中得到后者. 对于 1.8.7 我太年轻了,但我经常想知道没有它人们如何相处。)你只需要记住在最后返回 h ,作为 each只是返回它的接收者。

所以改成:

h = {}
g.each do |book,authors|
authors.each { |author| (h[author] ||= []) << book }
end
h
#=> {"author B"=>["Book Y", "Book X"],
# "author C"=>["Book Y", "Book X"],
# "author A"=>["Book X"]}

关于Ruby - 如何用数组值反转哈希?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/28655221/

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