我想计算用户之间的相似性,这是互惠的。
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中获得类似的行为?
答案 0 :(得分:6)
答案 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
此代码已使用ruby 1.8.2进行测试。当然,不要期待太多表现......