2012-12-21 31 views
0

我有一個類,其中的數據存儲爲set,我希望能夠比較該類的對象,使元素的字母大小寫無關緊要。例如,如果該集合包含字符串元素,則不應有差異"a""A"如何讓設置差異對大小寫不敏感?

爲此,我曾試圖定義一組成員的eql?方法是不敏感的區分,但是這對中集的方法-(化名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

一個明顯的解決方法是將所有字符串轉換爲低/大寫的情況下添加到集 – akonsu

+0

@akonsu我想避免這一點。 –

+1

糾正我,如果我錯了,但不會使用'eql?'設置元素使插入O(n)? – Dogbert

回答

2

好吧,首先,你只是存儲從SomeSet#add字符串,你需要存儲的Element一個實例,像這樣:

def add(o) 
    @elements.add(Element.new(o)) 
    self 
end 

而且你需要在你的Element實施hash方法類。

您可以將Element#@element轉換爲小寫,並傳遞其散列。

def hash 
    element.downcase.hash 
end 

全部代碼和演示:http://codepad.org/PffThml2

編輯:對於我的O(n)的插入註釋,上面:

的插入是O(1)。從我所看到的,eql?只與2個元素的hash一樣使用。因爲我們在元素的下降版本上做的是hash,所以它的分佈很好,並且不應該調用太多(如果它被調用的話)。

+0

糟糕,第一件事是我在將問題解決到MWE時犯的一個錯誤。 –

1

從文檔:

每對元件中的根據對象#EQL確定平等?和Object#散列,因爲Set使用散列作爲存儲。

也許你也需要實現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? 
+0

如何才能實現呢? –

+0

我已經更新了我的答案。我無法重新打開String類以避免使用我的自定義類String2。出於某種原因,當我向一個集合添加一個字符串時,我的重載比較運算符不會被調用。 – akonsu