2016-01-15 18 views
9

Sto provando a ordinare una matrice con una miscela di interi e stringhe. Prendiamo ad esempio:Come ordinare un array di interi e stringhe?

a = ["a", "b", 5, "c", 4, "d", "a1", "a12", 3, 13, 2, "13a", "12a"] 

ho provato:

a.sort do |x, y| 
    if x.class == y.class 
    x <=> y 
    else 
    x.class.to_s <=> y.class.to_s 
    end 
end 

che restituisce:

[2, 3, 4, 5, 13, "12a", "13a", "a", "a1", "a12", "b", "c", "d"] 

Il risultato che voglio è:

[2, 3, 4, 5, "12a", 13, "13a", "a", "a1", "a12", "b", "c", "d"] 
+0

Può esserci più di un numero nelle stringhe, ad es. ' "A1B2C3"'? – Stefan

+0

Che cosa è corretto? '[" a1 "," a12 "," a2 "]' o '[" a1 "," a2 "," a12 "]'? – Stefan

+0

@Stefan Possibile avere più di un numero in una stringa. Quest'ultimo '[" a1 "," a2 "," a12 "]' –

risposta

11
a.sort_by { |x| [(x.to_s.match(/^\d+/) ? x.to_i : 1.0/0), x.to_s] } 

L'idea è di ordinare prima il valore numerico e poi il valore stringa. Se la stringa non inizia con un valore numerico, considerare con forza il valore numerico come infinito.


EDIT: Come OP ha chiarito che vuole prendere in considerazione non solo il valore numerico che porta, ma tutto ciò che seguono, possiamo usare la stessa idea, solo per questa volta dobbiamo applicarlo su ogni singolo entità numerica e non numerica nella stringa:

a.sort_by do |x| 
    x.to_s.split(/(\D+)/).map do |y| 
    [(y.match(/\d/) ? y.to_i : 1.0/0), y] 
    end 
end 
+1

Un '0' nella matrice finirebbe tra' "13a" 'e' "a" ' – Stefan

+0

@Stefan, aggiornato. – ndn

+0

Questo è meglio, ma non ordina '[" a13 "," a2 "]' correttamente. – Stefan