2009-09-01 17 views
1

私はユーザー間の相反性を計算したいと思います。ルビーの順序付けられていないカップル

similarity[:user1][:user2] == similarity[:user2][:user1]

だから、使用する素晴らしいことだ:

unordered_set(:user1, :user2) = 1 
unordered_set(:user2, :user1) += 1 

read_unordered_set(:user1, :user2) #=> 2 
read_unordered_set(:user2, :user1) #=> 2 

どのように私はRubyで同様の動作を得ることができますか?

答えて

6

http://www.ruby-doc.org/core/classes/Set.html

[1, 2].to_set == [2, 1].to_set 

ここに欠けている部分がシンボルの< =>演算子ある...

+0

@ collimarco:この回答は、セットが順序付けされておらず、定義によって重複を含んでいないために機能します。 –

1

を助けるかもしれません。あなたは1を定義した場合、解決策は次のようになります。

# We define our own <=> operation on symbols 
Symbol.class_eval do 
    def <=>(other) 
    self.to_s <=> other.to_s 
    end 
end 


# Our set 
class UnorderedSet 
    def initialize 
    @hash = Hash.new 
    end 

    def [](k1, k2) 
    @hash[[k1, k2].sort] 
    end 

    def []=(k1, k2, value) 
    @hash[[k1, k2].sort] = value 
    end 

    def keys 
    @hash.keys 
    end 

    def values 
    @hash.values 
    end 

    def each 
    @hash.each do |k, v| 
     yield(k, v) 
    end 
    end 
    include Enumerable 
end 

は、その後のもちろん、私たちはそのコンテナのためのいくつかのテストを提供します。

if __FILE__ == $0 
    require 'test/unit' 

    class UnorderedSetTest < Test::Unit::TestCase 
    def setup 
     @set = UnorderedSet.new 
    end 

    def test_bracket_operators 
     assert_equal(nil, @set[:unknown, :key]) 

     @set[:user1, :user2] = 1 
     @set[:user2, :user1] += 1 

     assert_equal(2, @set[:user1, :user2]) 
     assert_equal(2, @set[:user2, :user1]) 
    end 

    def test_enumerability 
     h = { 
     [:user1, :user2] => "ruby", 
     [:c, :d] => "is", 
     [:b, :a] => "easy", 
     [:f, :e] => "!" 
     } 

     h.each do |k, v| 
     @set[*k] = v 
     end 

     assert_equal(h.values.sort, @set.values.sort) 
     assert_equal(h.keys.collect { |k| k.sort }.sort, @set.keys.sort) 
     assert_equal(h.to_a.collect { |k, v| [k.sort, v] }.sort, @set.to_a.sort) 
    end 
    end 
end 

このコードをルビー1.8.2でテストされました。もちろん、パフォーマンスはあまり期待しないでください。

関連する問題