<强>这是红宝石1.8问题:

我们都知道如何使用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"}]
有帮助吗?

解决方案

它已经在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"}]

其他提示

为使阵列#uniq的工作,为的任何的对象,你必须覆盖两个方法:?哈希和EQL

的所有对象都有其计算该对象的散列值的散列方法,所以对于两个对象为等于它们的值时也散列必须相等。

实施例 - 一个用户是唯一的时,他们的电子邮件地址是唯一的:

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"]

的问题是,Hash#hashHash#eql?既让在红宝石1.8.6虚假结果。这是非常罕见的猴子补丁我一直愿意对一个,因为这个错误严重地破坏了大量的代码 - 特别是memoizing功能。只是要小心猴子补丁,你不重写非正常的行为。

所以:

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只是产生一个错误。

这个怎么样?

h={}
[{"three"=>"3"}, {"three"=>"4"}, {"three"=>"3"}].select {|e| need=!h.key?(e) ; h[e]=1 ; need} 
#=> [{"three"=>"3"}, {"three"=>"4"}]

我碰到的这个我很多次。在红宝石1.8.6散列平等坏:

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

通行证在红宝石1.9和Ruby 1.8.7,在失败的Ruby 1.8.6。

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_by通过块的散列值或散列密钥。

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top