Building Hash by grouping array of objects based on a property of the items

后端 未结 3 589
太阳男子
太阳男子 2021-02-05 07:53

I\'m wondering if there is a more canonical way to do this in ruby 1.9

I have an array with a bunch of objects and I want to group them into a Hash using a property of e

相关标签:
3条回答
  • 2021-02-05 08:03

    You can also accomplish this by chaining methods... which might only be of academic interest for this problem, but is still a good technique to be familiar with.

    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> 
    
    0 讨论(0)
  • 2021-02-05 08:21

    Phrogz is correct, group_by is there for the taking. Your code contains one of ruby's gotcha's.

    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]
    

    Output

    {}
    []
    {}
    ["a", "b", "c", "d", "ab", "bc", "de", "abc"]
    ["a", "b", "c", "d", "ab", "bc", "de", "abc"]
    
    0 讨论(0)
  • 2021-02-05 08:26

    Ruby has anticipated your need, and has got you covered with 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"]}
    

    In Ruby 1.9, you can make this even shorter with:

    irb(main):003:0> aers.group_by(&:size)
    #=> {1=>["a", "b", "c", "d"], 2=>["ab", "bc", "de"], 3=>["abc"]}
    
    0 讨论(0)
提交回复
热议问题