Per alcune implementazioni di Ruby, specie è stabile, ma non dovresti dipendere da questo. La stabilità di Ruby è definita dall'implementazione.
Cosa dice la documentazione
The documentation dice che non si deve dipendere sorta essere stabile:
Il risultato non è garantito per essere stabile. Quando il confronto di due elementi restituisce 0, l'ordine degli elementi è imprevedibile.
Si noti che questo non dice se l'ordinamento è stabile o meno. Dice solo che non è garantito che sia stabile. Qualsiasi implementazione data di Ruby potrebbe avere un ordinamento stabile e comunque essere coerente con la documentazione. Potrebbe anche avere un ordinamento instabile o cambiare se l'ordinamento è stabile in qualsiasi momento.
Cosa Rubino realmente fa
stampe codice
Questa prova true
se sorta di Ruby è stabile, o false
se non è:
Foo = Struct.new(:value, :original_order) do
def <=>(foo)
value <=> foo.value
end
end
size = 1000
unsorted = size.times.map do |original_order|
value = rand(size/10)
Foo.new(value, original_order)
end
sorted = unsorted.sort
stably_sorted = unsorted.sort_by do |foo|
[foo.value, foo.original_order]
end
p [RUBY_PLATFORM, RUBY_VERSION, RUBY_PATCHLEVEL, sorted == stably_sorted]
Ecco i risultati per tutti i rubini che ho installato su la mia macchina Linux:
["java", "1.8.7", 357, false]
["java", "1.9.3", 551, false]
["x86_64-linux", "1.8.7", 374, false]
["x86_64-linux", "1.8.7", 374, false]
["x86_64-linux", "1.8.7", 376, false]
["x86_64-linux", "1.9.3", 392, false]
["x86_64-linux", "1.9.3", 484, false]
["x86_64-linux", "1.9.3", 551, false]
["x86_64-linux", "2.0.0", 643, false]
["x86_64-linux", "2.0.0", 648, false]
["x86_64-linux", "2.1.0", 0, false]
["x86_64-linux", "2.1.10", 492, false]
["x86_64-linux", "2.1.1", 76, false]
["x86_64-linux", "2.1.2", 95, false]
["x86_64-linux", "2.1.3", 242, false]
["x86_64-linux", "2.1.4", 265, false]
["x86_64-linux", "2.1.5", 273, false]
["x86_64-linux", "2.1.6", 336, false]
["x86_64-linux", "2.1.7", 400, false]
["x86_64-linux", "2.1.8", 440, false]
["x86_64-linux", "2.1.9", 490, false]
["x86_64-linux", "2.2.0", 0, true]
["x86_64-linux", "2.2.1", 85, true]
["x86_64-linux", "2.2.2", 95, true]
["x86_64-linux", "2.2.3", 173, true]
["x86_64-linux", "2.2.4", 230, true]
["x86_64-linux", "2.2.5", 319, true]
["x86_64-linux", "2.2.6", 396, true]
["x86_64-linux", "2.3.0", 0, true]
["x86_64-linux", "2.3.1", 112, true]
["x86_64-linux", "2.3.2", 217, true]
["x86_64-linux", "2.3.3", 222, true]
["x86_64-linux", "2.4.0", 0, true]
["x86_64-linux", "2.4.0", -1, true]
["x86_64-linux", "2.4.0", -1, true]
["x86_64-linux", "2.4.0", -1, true]
["x86_64-linux", "2.4.0", -1, true]
["x86_64-linux", "2.4.1", 111, true]
possiamo vedere che JRuby è instabile, e la risonanza magnetica prima di 2,2, su Linux, è instabile. MRI> = 2.2.0 è stabile (di nuovo, su Linux).
La piattaforma è importante. Anche se il risultato di cui sopra dimostra che tipo è stabile nelle MRI 2.4.1 su Linux, la stessa versione è instabile su Windows:
["x64-mingw32", "2.4.1", 111, false]
Perché è di risonanza magnetica ordinamento stabile su Linux, ma non su Windows?
Anche all'interno di una singola versione di un'implementazione di Ruby, l'algoritmo di ordinamento può cambiare. La risonanza magnetica può utilizzare almeno tre diversi tipi. La routine di ordinamento viene selezionata in fase di compilazione utilizzando una serie di #ifdefs in util.c. Sembra che la risonanza magnetica abbia la possibilità di utilizzare i tipi da almeno due diverse librerie. Ha anche una sua implementazione.
Cosa dovresti fare al riguardo?
Poiché l'ordinamento può essere stabile ma non può essere garantito stabile, non scrivere codice che dipenda dal fatto che il tipo di Ruby sia stabile. Tale codice potrebbe interrompersi se utilizzato su una versione, un'implementazione o una piattaforma diversa.
No, almeno non come l'hai fatto. In che modo 'sort' garantisce l'ordine di due elementi quando i rispettivi comparatori sono uguali? – Linuxios
@Linuxios: alcuni algoritmi di ordinamento sono [stable] (http://en.wikipedia.org/wiki/Stable_sort#Stability). –
@mu: Grazie. Interessante. Non penso però che Ruby sia. – Linuxios