I have a class in which the data is stored as a set and I want to be able to compare objects of that class such that the letter case of the elements is of no matter. For example if the set contains elements that are strings there should be no difference of "a" and "A".
To do this I have tried to define the eql? method of the set members to be insensitive to case but this has no effect on the method - (alias difference) in Set. So, how should I go about to make - insensitive to case?
The following code illustrates the problem:
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?
Ok, firstly, you’re just storing strings from
SomeSet#add, you need to store an instance ofElement, like so:And you need to implement a
hashmethod in yourElementclass.You can convert
Element#@elementto lowercase, and pass on its hash.Full code and demo: http://codepad.org/PffThml2
Edit: For my O(n) insertion comment, above:
Insertions are O(1). From what I can see,
eql?is only used with thehashof 2 elements is same. As we’re doinghashon the downcased version of the element, it will be fairly well distributed, andeql?shouldn’t be called much (if it is called at all).