我正在开展一个项目,我需要将报纸文章与它们在印刷品中出现的页码相关联。
我的输入数据只是一堆文章标题和页码。我想出了以下代码来创建一个新的Hash
,其中键是页码,值是文章标题的数组:
a = ["A1", "title 1"]
b = ["A1", "title 2"]
c = ["A2", "title 3"]
hash = {}
articles = [a,b,c]
articles.each do |a|
if hash.has_key?(a[0])
hash[a[0]] << a[1]
else
hash.merge!({a[0] => [a[1]]})
end
end
代码运行良好,但我想知道是否有更简洁的方法。我检查了Ruby文档,找不到任何内置方法,但我想对此进行输入。
答案 0 :(得分:2)
由于Michael Kohl最近一直提醒group_by
:
articles = [
["A1", "title 1"],
["A1", "title 2"],
["A2", "title 3"]
]
page_to_titles = articles.group_by(&:first).each { |k,v| v.map!(&:last) }
在1.9.2和1.8.7中使用相同的内容。
答案 1 :(得分:1)
articles.inject(Hash.new) do |hash, (page, title)|
h[page] ||= []
h[page] << title
h
end
答案 2 :(得分:1)
[a,b,c].inject(Hash.new{ |h,k| h[k] = [] }) { |res,(p,t)| res[p] << t; res }
或仅适用于红宝石1.9:
[a,b,c].each_with_object(Hash.new{ |h,k| h[k] = [] }) { |(p,t),res| res[p] << t }
答案 3 :(得分:0)
您可以更好地描述自己的行为,并使用警卫||=
代替if
。我会像这样重构它:
articles = []
articles << ["A1", "title 1"]
articles << ["A1", "title 2"]
articles << ["A2", "title 3"]
PAGE = 0
TITLE = 1
def merge_articles(articles)
res = {}
articles.each do |a|
res[a[PAGE]] ||= []
res[a[PAGE]] << a[TITLE]
end
res
end
hash = merge_articles(articles)
答案 4 :(得分:0)
这应该适用于Ruby 1.9:
articles.inject({}) do |hash, (page, title)|
hash.tap do |h|
h[page] ||= []
h[page] << title
end
end