2

これは Ruby 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"}]
4

6 に答える 6

6

Array#uniq を任意のオブジェクトで機能させるには、hash と eql? の 2 つのメソッドをオーバーライドする必要があります。

すべてのオブジェクトには、そのオブジェクトのハッシュ値を計算するハッシュ メソッドがあるため、2 つのオブジェクトが等しくなるためには、ハッシュされたときの値も等しくなければなりません。

例 - 電子メール アドレスが一意である場合、ユーザーは一意です。

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"]
于 2010-11-12T21:24:04.963 に答える
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"}]
于 2009-10-13T04:40:51.013 に答える
2

問題はHash#hashHash#eql?どちらも Ruby 1.8.6 で偽の結果を返すことです。これは非常にまれなモンキー パッチの 1 つです。なぜなら、このバグは多くのコード (特にメモ化機能) を深刻に破壊するからです。壊れていない動作を上書きしないモンキー パッチには注意してください。

そう:

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 で開始された場合にエラーを発生させるだけです。

于 2009-10-13T15:51:38.503 に答える
1

これはどう?

h={}
[{"three"=>"3"}, {"three"=>"4"}, {"three"=>"3"}].select {|e| need=!h.key?(e) ; h[e]=1 ; need} 
#=> [{"three"=>"3"}, {"three"=>"4"}]
于 2009-10-13T07:27:56.717 に答える
1

私はこれに何度も遭遇しました。Ruby 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

Ruby 1.9 と Ruby 1.8.7 で合格、Ruby 1.8.6 で不合格。

于 2009-10-13T15:14:46.563 に答える
0
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 するだけです。

于 2011-10-14T17:12:39.790 に答える