2009-09-01 4 views
1

Je voudrais calculer la similitude entre les utilisateurs, ce qui est réciproque.Couple non ordonné en Ruby

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

Il serait génial d'utiliser:

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

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

Comment puis-je obtenir un comportement similaire à Ruby?

Répondre

6

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

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

pourraient être utiles ...

+0

@collimarco: Cette réponse fonctionne parce que les ensembles ne sont pas ordonnés et ne contiennent pas de doublons par définition. –

1

La partie manquante est ici un < => opérateur sur les symboles. Si vous définissez une, puis une solution serait:

# 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 

que nous fournissons, bien sûr, des tests pour ce conteneur:

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 

Ce code a été testé avec Ruby 1.8.2. Bien sûr, ne vous attendez pas à beaucoup de performances ...

Questions connexes