2011-07-15 10 views

Respuesta

17

Hice una pequeña prueba de referencia con diferentes combinaciones de uniq uniq! ordenar y ordenar! No hay diferencias significativas:

   user  system  total  real 
sort!.uniq!103.547000 0.172000 103.719000 (104.093750) 
uniq!.sort!100.437000 0.093000 100.530000 (100.859375) 
uniq.sort 100.516000 0.157000 100.673000 (101.031250) 
sort.uniq 103.563000 0.062000 103.625000 (103.843750) 

Lo que no se puede usar es algo así como:

array = [1] 
array.uniq!.sort! 

uniq! dará como resultado nil y sort! lanzará una excepción.

El índice de referencia que utiliza:

require 'benchmark' 
require 'date' 

TEST_LOOPS = 10_000 
ARRAY = [] 
1000.times{ 
    ARRAY << Date.new(1900 + rand(100), rand(11)+1, rand(27) + 1) 
} 
Benchmark.bm(10) {|b| 

    b.report('sort!.uniq!') { 
    TEST_LOOPS.times { 
     a = ARRAY.dup 
     a.sort! 
     a.uniq! 
    }   #Testloops 
    }    #b.report 

    b.report('uniq!.sort!') { 
    TEST_LOOPS.times { 
     a = ARRAY.dup 
     # uniq!.sort! not possible. uniq! may get nil 
     a.uniq! 
     a.sort! 
    }   #Testloops 
    }    #b.report 

    b.report('uniq.sort') { 
    TEST_LOOPS.times { 
     a = ARRAY.dup.uniq.sort 
    }   #Testloops 
    }    #b.report 

    b.report('sort.uniq') { 
    TEST_LOOPS.times { 
     a = ARRAY.dup.sort.uniq 
    }   #Testloops 
    }    #b.report 

} #Benchmark 
+0

Gracias por proporcionar una prueba de referencia y por señalar el problema potencial con '.uniq! .sort!' –

+0

Este no es un buen punto de referencia porque el p la diferencia de rendimiento entre '.uniq.sort!' y '.sort! .uniq!' depende en gran medida de los datos que se ordenan. Está probando la misma matriz pseudoaleatoria una y otra vez, por lo que si tiene muy pocos elementos duplicados (que creo que es el caso aquí), el efecto de 'uniq' será insignificante. – Max

+0

Esto también se encuentra en la otra respuesta http://stackoverflow.com/a/21376982/676874. (y recomendaría al asker que acepte la otra respuesta). – knut

5

Realmente no importa en qué dirección lo hace. Supongo que el uniq primero, por lo que resulta en menos elementos para ordenar con un pase a través de la matriz. Entonces usted puede hacer

a=[3,3,3,3,6,7,1,1,1,1,3] 
a.uniq! 
a.sort! 
+2

? ¿O es el primer '!' Innecesario? –

+1

¡El primero! es innecesario porque eso significa que está reemplazando su matriz original. ¡El uniq no tiene que reemplazarlo porque está pasando el valor de retorno para ordenarlo! que luego reemplazará su matriz original con el valor final. –

+2

¡Eso no es verdad! Primero obtienes una copia por 'uniq', y luego esta copia se reemplaza por' sort! '. Entonces, si quieres ordenar y hacer uniq en su lugar, debes usar tanto 'uniq!' Como 'sort!'. Pruébalo en irb y prueba con 'igual?'. – mliebelt

0

Correr uno o el otro primero depende de las necesidades de su aplicación.

1) A menos que tenga matrices enormes, ejecute la primera que tenga más sentido. ¿Estás usando la matriz ordenada o única en otro lugar? ¿Una orden se ajusta más naturalmente a la lógica de su aplicación?

2) Si tiene matrices enormes, y me refiero a enorme en base a una determinación real medida de que su código tarda demasiado en ejecutar array.sort!.uniq!, entonces puede intentar con la otra orden y ver. Si tiene muchos duplicados, entonces array.uniq!.sort! podría ser un poco más rápido.

3) Si le preocupa la velocidad, es probable que desee utilizar sort_by. Ver por ejemplo, https://github.com/JuanitoFatas/fast-ruby/blob/master/code/enumerable/sort-vs-sort_by.rb

+0

Esta es una serie de 'Date's, por lo que no definen el tipo (IE sólo estoy ejecutando' array_name.sort! '' sin clase {cómo ordenar} '. ¿Sería' sort_by' todavía ser una ventaja? Si es así, ¿qué le pasa a 'sort_b'y? –

+0

Si utiliza _array.uniq! .Sort! _ puede obtener una excepción. Sólo trate _ [1] .uniq! .Sort! _ – knut

+0

Es cierto que' uniq gama #! '' devuelve las negativas si la matriz ya es único, pero haciendo 'array.uniq.sort!' no va a lograr lo que pidió a David. 'array' no será clasificado. –

7

De hecho, depende del número de valores únicos. En el ejemplo de knut, el conjunto de inicio podría incluir como máximo 365 valores únicos de cada 1000, y el orden de las operaciones parecía no tener influencia.

si 'uniq' reduce significativamente el tamaño de la matriz, hay una clara ventaja en ejecutarlo primero.

A=[] 
10_000.times do 
    A << rand(80) 
end 

Benchmark.bm(10) do |b| 
    b.report "sort.uniq" do 
    10_000.times {A.sort.uniq} 
    end 
    b.report "uniq.sort" do 
    10_000.times {A.uniq.sort} 
    end 
end 

       user  system  total  real 
sort.uniq 20.202000 0.281000 20.483000 (20.978098) 
uniq.sort 9.298000 0.000000 9.298000 ( 9.355936) 

No he probado el '.uniq! .sort!' permutaciones, pero creo que deberían seguir el resultado anterior.

Este ejemplo puede ser un poco extremo, pero no veo por qué uno no siempre se debe ejecutar qué necesitaría hacer `array_name.uniq! .Sort!` '' .uniq primeros

Cuestiones relacionadas