2010-07-13 12 views
43

Posso generare poche righe di codice che lo faranno, ma mi chiedo se c'è un bel modo Rubyesque per farlo. Nel caso in cui non sia stato chiaro, quello che sto cercando è un metodo array che restituirà true se fornito (per esempio) [3,3,3,3,3] o ["rabbits","rabbits","rabbits"] ma restituirà false con [1,2,3,4,5] o ["rabbits","rabbits","hares"].Come si verifica se tutti gli elementi in una matrice sono identici?

Grazie

risposta

54
class Array 
    def same_values? 
    self.uniq.length == 1 
    end 
end 


[1, 1, 1, 1].same_values? 
[1, 2, 3, 4].same_values? 

Che dire di questo? Tuttavia, restituisce false per un array vuoto, è possibile modificarlo in < = 1 e in questo caso restituirà true. A seconda di cosa hai bisogno.

+2

È molto elegante. Posso semplicemente usare .uniq.length == 1 direttamente nel mio codice piuttosto che nel modo in cui l'hai fatto (lo sto usando solo una volta, quindi lo terrò ASCIUTTO). Sarebbe bello se ci fosse un built-in .same_values? metodo. Non ho bisogno di preoccuparmi per il caso di array vuoto nel mio codice come a) non dovrebbe venire nella mia situazione eb) se lo facesse vorrei che restituisca false. Grazie. – brad

+2

Nota che 'uniq' usa' hash' e 'eql?' E non '==' che può o non può essere quello che vuoi. –

+1

Si potrebbe ovviamente estendere questo agli array annidati con self.flatten.uniq.lenth == 1 –

67

È possibile utilizzare Enumerable#all? che restituisce vero se il blocco specificato restituisce true per tutti gli elementi della collezione.

array.all? {|x| x == array[0]} 

(Se l'array è vuoto, il blocco non viene mai chiamato, così facendo array[0] è al sicuro.)

+0

ne dite '(array.any {| x | x = array [0]!}?)'!? Non eseguirà iterazioni su tutti gli elementi dopo la prima occorrenza di un valore diverso. –

+4

@ Nu-hin Né sarà tutto? '. – sepp2k

+0

Sì, mio ​​male, grazie. –

9

Anch'io preferisco rispondere meglio, breve e dolce. Se tutti gli elementi sono stati dalla stessa classe Enumerable, come numerico o String, si potrebbe utilizzare

def all_equal?(array) array.max == array.min end 
+0

Chiazza di petrolio. Molto lucido – brad

+2

Non è necessario che gli oggetti siano nella stessa classe, devono semplicemente essere in grado di implementare '<=>' (l'operatore dell'astronave). –

+0

@AndrewGrimm L'operatore dell'astronave causa il fallimento di questo codice se gli oggetti sono di diverso tipo. –

1

ho utilizzato:

def add_equal?(arr) arr.reduce { |x,y| x == y ? x : nil } end 

può fallire quando arr contiene nil.

1

userei:

array = ["rabbits","rabbits","hares", nil, nil] 
array.uniq.compact.length == 1 
Problemi correlati