代码之家  ›  专栏  ›  技术社区  ›  khelll

扩展uniq方法

  •  2
  • khelll  · 技术社区  · 15 年前

    我们都知道如何使用 Array#uniq :

    [1,2,3,1].uniq #=> [1,2,3]
    

    然而,我想知道我们是否可以用猴子补丁的方式来处理复杂的对象。当前行为如下所示:

    [{"three"=>"3"}, {"three"=>"4"}, {"three"=>"3"}].uniq 
    #=> [{"three"=>"3"}, {"three"=>"4"}, {"three"=>"3"}]
    

    所要求的是:

    [{"three"=>"3"}, {"three"=>"4"}, {"three"=>"3"}].uniq 
    #=> [{"three"=>"3"}, {"three"=>"4"}]
    
    6 回复  |  直到 15 年前
        1
  •  4
  •   DigitalRoss    15 年前

    它已经在1.8.7中对我起作用了。

    1:~$ ruby -v
    ruby 1.8.7 (2008-08-11 patchlevel 72) [i486-linux]
    1:~$ irb -v
    irb 0.9.5(05/04/13)
    1:~$ irb
    >> [{"three"=>"3"}, {"three"=>"4"}, {"three"=>"3"}].uniq 
    => [{"three"=>"3"}, {"three"=>"4"}]
    
        2
  •  6
  •   Ryan Horrisberger    14 年前

    使数组#uniq工作

    所有对象都有一个散列方法,该方法计算该对象的散列值,因此,要使两个对象相等,它们在散列时的值也必须相等。

    示例--当用户的电子邮件地址是唯一的时,该用户是唯一的:

    class User
      attr_accessor :name,:email
    
      def hash
        @email.hash
      end
    
      def eql?(o)
        @email == o.email
      end
    end
    
    >> [User.new('Erin Smith','roo@example.com'),User.new('E. Smith','roo@example.com')].uniq 
    => [#<User:0x1015a97e8 @name="Erin Smith", @email="maynurd@example.com"]
    
        3
  •  2
  •   Bob Aman    15 年前

    问题是 Hash#hash Hash#eql? 在Ruby 1.8.6中,两者都给出了虚假的结果。这是我愿意执行的非常罕见的monkey补丁之一,因为这个bug严重破坏了很多代码,尤其是记忆功能。只是要小心使用猴子补丁,不要覆盖未破坏的行为。

    因此:

    class Hash
      if {}.hash != {}.hash
        def hash
          # code goes here
        end
      end
      if !{}.eql?({})
        def eql?(other)
          # code goes here
        end
      end
    end
    

    但是,如果您正在执行一些控制部署环境的操作,那么如果应用程序是从1.8.6开始的,只需发出一个错误。

        4
  •  1
  •   pierrotlefou    15 年前

    这个怎么样?

    h={}
    [{"three"=>"3"}, {"three"=>"4"}, {"three"=>"3"}].select {|e| need=!h.key?(e) ; h[e]=1 ; need} 
    #=> [{"three"=>"3"}, {"three"=>"4"}]
    
        5
  •  1
  •   Jörg W Mittag    15 年前

    require 'test/unit'
    
    class TestHashEquality < Test::Unit::TestCase
      def test_that_an_empty_Hash_is_equal_to_another_empty_Hash
        assert({}.eql?({}), 'Empty Hashes should be eql.')
      end
    end
    

    通过Ruby 1.9和Ruby 1.8.7,在Ruby 1.8.6中失败。

        6
  •  0
  •   Race    13 年前
    1.8.7 :039 > [{"three"=>"3"}, {"three"=>"4"}, {"three"=>"3"}].uniq {|x|x.values} 
    => [{"three"=>"3"}, {"three"=>"4"}] 
    1.8.7 :040 > [{"three"=>"3"}, {"three"=>"4"}, {"three"=>"3"}].uniq {|x|x.keys}
    => [{"three"=>"3"}] 
    

    那样的怎么样?只需通过块通过散列值或散列键uniq_。