我有一个类,其中数据存储为set,我希望能够比较该类的对象,使得元素的字母大小写无关紧要。例如,如果集合包含字符串元素,那么"a"
和"A"
之间应该没有区别。
为此,我尝试将set成员的eql?
方法定义为对case不敏感,但这对Set中的方法-
(别名difference
)没有影响。那么,我应该如何使-
对案件不敏感?
以下代码说明了问题:
require 'set'
class SomeSet
include Enumerable
def initialize; @elements = Set.new; end
def add(o)
@elements.add(o)
self
end
def each(&block) # To enable +Enumerable+
@elements.each(&block)
end
def difference(compared_list)
@elements - compared_list
end
end
class Element
attr_reader :element
def initialize(element); @element = element; end
# This seems to have no effect on +difference+
def eql?(other_element)
element.casecmp(other_element.element) == 0
end
end
set1 = SomeSet.new
set2 = SomeSet.new
set1.add("a")
set2.add("A")
# The following turns out false but I want it to turn out true as case
# should not matter.
puts set1.difference(set2).empty?
答案 0 :(得分:2)
好的,首先,您只是存储来自SomeSet#add
的字符串,您需要存储Element
的实例,如下所示:
def add(o)
@elements.add(Element.new(o))
self
end
您需要在hash
课程中实施Element
方法。
您可以将Element#@element
转换为小写,然后传递其哈希值。
def hash
element.downcase.hash
end
完整代码和演示:http://codepad.org/PffThml2
编辑:对于我的O(n)插入评论,上面是:
插入是O(1)。从我所看到的情况来看,eql?
仅用于hash
的2个元素是相同的。当我们对元素的下层版本进行hash
时,它将分布得相当好,并且eql?
不应被调用太多(如果它被调用的话)。
答案 1 :(得分:1)
来自文档:
每个元素的相等性是根据Object#eql确定的?和Object#hash,因为Set使用Hash作为存储。
也许您还需要实现Object#hash。
require 'set'
class String2
attr_reader :value
def initialize v
@value = v
end
def eql? v
value.casecmp(v.value) == 0
end
def hash
value.downcase.hash
end
end
set1 = Set.new
set2 = Set.new
set1.add(String2.new "a")
set2.add(String2.new "A")
puts set1.difference(set2).empty?