2009-07-09 21 views

risposta

16

Basta rendere il caso coerente per primo.

esempio:

["a","A"].map{|i| i.downcase}.uniq 

Edit: Se come mikej suggerisce, gli elementi restituiti devono essere esattamente lo stesso come nella matrice originale, allora questo lo farà per voi:

a.inject([]) { |result,h| result << h unless result.map{|i| i.downcase}.include?(h.downcase); result } 

Modifica2 Soluzione che dovrebbe soddisfare mikej :-)

downcased = [] 
a.inject([]) { |result,h| 
     unless downcased.include?(h.downcase); 
      result << h 
      downcased << h.downcase 
     end; 
     result} 
+0

Mentre questo avrebbe funzionato per l'esempio dato se la lista fosse qualcosa di simile ["Hello", "HELLO"] quindi ["Hello", "HELLO"]. Map {| i | i.downcase} .uniq restituirebbe "[hello"] che non corrisponde a nessuna delle stringhe nell'elenco originale. – mikej

+0

La soluzione modificata è buona, tranne che costruirà la lista downcased usando result.map {| i | i.downcase} più volte (una volta per ogni elemento nell'elenco originale), quindi forse eseguirlo una volta come istruzione separata e memorizzare in una variabile temporanea se l'elenco è di grandi dimensioni. – mikej

+1

La soluzione di @Eric C è molto più semplice. – depquid

4
["a", "A"].map{|x| x.downcase}.uniq 
=> ["a"] 

o

["a", "A"].map{|x| x.upcase}.uniq 
=> ["A"] 
+0

Ack! Picchiato! – Codebeef

0

Una soluzione più generale (anche se non il più efficiente):

class EqualityWrapper 
    attr_reader :obj 

    def initialize(obj, eq, hash) 
    @obj = obj 
    @eq = eq 
    @hash = hash 
    end 

    def ==(other) 
    @eq[@obj, other.obj] 
    end 

    alias :eql? :== 

    def hash 
    @hash[@obj] 
    end 
end 

class Array 
    def uniq_by(eq, hash = lambda{|x| 0 }) 
    map {|x| EqualityWrapper.new(x, eq, hash) }. 
    uniq. 
    map {|x| x.obj } 
    end 

    def uniq_ci 
    eq = lambda{|x, y| x.casecmp(y) == 0 } 
    hash = lambda{|x| x.downcase.hash } 
    uniq_by(eq, hash) 
    end 
end 

Il metodo uniq_by prende un lambda che controlla l'uguaglianza, e un lambda che restituisce un hash e rimuove gli oggetti duplicati come definito da tali dati.

Implementato in aggiunta a questo, il metodo uniq_ci rimuove i duplicati di stringa utilizzando confronti senza distinzione tra maiuscole e minuscole.

7

è possibile creare una mappatura (hash) tra il caso normalizzato (ad es.downcased) i valori e il valore effettivo e poi prendere solo i valori del hash:

["a", "b", "A", "C"]\ 
.inject(Hash.new){ |h,element| h[element.downcase] = element ; h }\ 
.values 

seleziona l'ultima occorrenza di una parola data (case insensitive):

["A", "b", "C"] 

se si desidera la prima occorrenza :

["a", "b", "A", "C"]\ 
.inject(Hash.new){ |h,element| h[element.downcase] = element unless h[element.downcase] ; h }\ 
.values 
+0

+1 Molto intelligente. – DanSingerman

2

Un po 'più efficiente e modo è quello di fare uso di chiavi uniq in hash, in modo da controllare questo:

["a", "A"].inject(Hash.new){ |hash,j| hash[j.upcase] = j; hash}.values 

tornerà l'ultimo elemento, in questo caso

["A"] 

mentre usando || = operatore assegnazione:

["a", "A"].inject(Hash.new){ |hash,j| hash[j.upcase] ||= j; hash}.values 

tornerà primo elemento, in questo caso

["a"] 

in particolare per i big Arrays, dovrebbe essere più veloce come non cerchiamo l'array ogni volta utilizzando include?

applausi ...

3

Se si utilizza ActiveSupport, è possibile utilizzare uniq_by. Non influisce sul caso dell'output finale.

['A','a'].uniq_by(&:downcase) # => ['A'] 
29

C'è un altro modo per farlo. Puoi effettivamente passare un blocco a uniq o uniq! che può essere utilizzato per valutare ciascun elemento.

["A", "a"].uniq { |elem| elem.downcase } #=> ["A"] 

o

["A", "a"].uniq { |elem| elem.upcase } #=> ["A"] 

In questo caso, però, tutto sarà case insensitive così sarà sempre tornare la matrice ["A"]

+6

Ottima risposta. Nota che una variazione leggermente più corta è '[" A "," a "]. Uniq (&: downcase)'. – antinome

+0

@antinome Molto più leggibile. –

+0

Questa dovrebbe essere la risposta accettata ... –

Problemi correlati