0

我有一个类,其中数据存储为一个集合,我希望能够比较该类的对象,以便元素的字母大小写无关紧要。例如,如果集合包含字符串元素,则"a"和应该没有区别"A"

为此,我尝试将eql?set 成员的方法定义为不区分大小写,但这对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?
4

2 回答 2

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?仅与hash2 个元素一起使用是相同的。正如我们在hash元素的小写版本上所做的那样,它将被很好地分布,并且eql?不应该被调用太多(如果它被调用的话)。

于 2012-12-21T17:24:44.020 回答
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?
于 2012-12-21T17:16:37.327 回答