【问题标题】:Building Hash by grouping array of objects based on a property of the items通过根据项目的属性对对象数组进行分组来构建哈希
【发布时间】:2011-01-14 15:09:46
【问题描述】:

我想知道在 ruby​​ 1.9 中是否有更规范的方法来做到这一点

我有一个包含一堆对象的数组,我想使用数组中每个对象的属性将它们分组为一个哈希。

非常简化示例:

> sh = {}
 => {} 
> aers = %w(a b c d ab bc de abc)
 => ["a", "b", "c", "d", "ab", "bc", "de", "abc"] 
> aers.each do |aer|
>     sh[aer.size] = [] if sh[aer.size].nil?
>     sh[aer.size] << aer
>   end
=> ["a", "b", "c", "d", "ab", "bc", "de", "abc"] 
> sh
 => {1=>["a", "b", "c", "d"], 2=>["ab", "bc", "de"], 3=>["abc"]} 

我试过这个,但它的输出是错误的(如你所见):

 sh = Hash.new([])
 => {} 
> aers.each do |aer|
>     sh[aer.size] << aer
>   end
 => ["a", "b", "c", "d", "ab", "bc", "de", "abc"] 
> sh
 => {} 

【问题讨论】:

标签: ruby arrays hash


【解决方案1】:

Ruby 已经预见到您的需求,并为您提供了Enumerable#group_by

irb(main):001:0> aers = %w(a b c d ab bc de abc)
#=> ["a", "b", "c", "d", "ab", "bc", "de", "abc"]

irb(main):002:0> aers.group_by{ |s| s.size }
#=> {1=>["a", "b", "c", "d"], 2=>["ab", "bc", "de"], 3=>["abc"]}

在 Ruby 1.9 中,您可以通过以下方式缩短它:

irb(main):003:0> aers.group_by(&:size)
#=> {1=>["a", "b", "c", "d"], 2=>["ab", "bc", "de"], 3=>["abc"]}

【讨论】:

  • 这就是Ruby如此酷的原因;它甚至在我们做之前就知道我们想要什么。
  • 请注意,在 1.8 中执行符号比仅使用块要慢得多。 confreaks.net/videos/… 检查 31:18。在 1.9 中,它们在性能上没有区别。
【解决方案2】:

Phrogz 是正确的,group_by 是可以接受的。您的代码包含 ruby​​ 的问题之一。

aers = %w(a b c d ab bc de abc)
sh = Hash.new([]) # returns the _same_ array everytime the key is not found. 
# sh = Hash.new{|h,v| h[v] = []}  # This one works
p sh, sh.default

aers.each do |aer|
  sh[aer.size] << aer  #modifies the default [] every time
end
p sh, sh.default
p sh[5]

输出

{}
[]
{}
["a", "b", "c", "d", "ab", "bc", "de", "abc"]
["a", "b", "c", "d", "ab", "bc", "de", "abc"]

【讨论】:

    【解决方案3】:

    您也可以通过链接方法来完成此操作...这可能只是对这个问题的学术兴趣,但仍然是一种需要熟悉的好技术。

    irb(main):017:0> sh = {}
    => {}
    irb(main):018:0> aers.collect{|k| k.size}.uniq!.each{|k| sh[k] = aers.select{|j| j.size == k}}
    => [1, 2, 3]
    irb(main):019:0> sh
    => {1=>["a", "b", "c", "d"], 2=>["ab", "bc", "de"], 3=>["abc"]}
    irb(main):020:0> 
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多