Uniq by object attribute in Ruby

前端 未结 14 1782
我寻月下人不归
我寻月下人不归 2020-11-30 23:20

What\'s the most elegant way to select out objects in an array that are unique with respect to one or more attributes?

These objects are stored in ActiveRecord so us

相关标签:
14条回答
  • 2020-11-30 23:39

    If I understand your question correctly, I've tackled this problem using the quasi-hacky approach of comparing the Marshaled objects to determine if any attributes vary. The inject at the end of the following code would be an example:

    class Foo
      attr_accessor :foo, :bar, :baz
    
      def initialize(foo,bar,baz)
        @foo = foo
        @bar = bar
        @baz = baz
      end
    end
    
    objs = [Foo.new(1,2,3),Foo.new(1,2,3),Foo.new(2,3,4)]
    
    # find objects that are uniq with respect to attributes
    objs.inject([]) do |uniqs,obj|
      if uniqs.all? { |e| Marshal.dump(e) != Marshal.dump(obj) }
        uniqs << obj
      end
      uniqs
    end
    
    0 讨论(0)
  • 2020-11-30 23:46

    You can use a hash, which contains only one value for each key:

    Hash[*recs.map{|ar| [ar[attr],ar]}.flatten].values
    
    0 讨论(0)
  • 2020-11-30 23:47

    Use Array#uniq with a block:

    @photos = @photos.uniq { |p| p.album_id }
    
    0 讨论(0)
  • 2020-11-30 23:47

    The most elegant way I have found is a spin-off using Array#uniq with a block

    enumerable_collection.uniq(&:property)
    

    …it reads better too!

    0 讨论(0)
  • 2020-11-30 23:47

    ActiveSupport implementation:

    def uniq_by
      hash, array = {}, []
      each { |i| hash[yield(i)] ||= (array << i) }
      array
    end
    
    0 讨论(0)
  • 2020-11-30 23:49

    I had originally suggested using the select method on Array. To wit:

    [1, 2, 3, 4, 5, 6, 7].select{|e| e%2 == 0} gives us [2,4,6] back.

    But if you want the first such object, use detect.

    [1, 2, 3, 4, 5, 6, 7].detect{|e| e>3} gives us 4.

    I'm not sure what you're going for here, though.

    0 讨论(0)
提交回复
热议问题