Неупорядоченная пара в рубине - PullRequest
1 голос
/ 01 сентября 2009

Я хотел бы рассчитать сходство между пользователями, которое является взаимным.

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?

Ответы [ 2 ]

6 голосов
/ 01 сентября 2009

http://www.ruby -doc.org / ядро ​​/ классы / Set.html

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

Могу помочь ...

1 голос
/ 01 сентября 2009

Недостающая часть здесь - это оператор <=> для символов. Если вы определите один, то решение будет:

# 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

Этот код был протестирован с ruby ​​1.8.2. Конечно, не ожидайте, что производительность будет большой ...

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...