array - ruby slice
¿Diferencia entre mapa y coleccionar en ruby? (5)
¡Los collect y collect! ¡Los métodos son alias para map y map! , por lo que pueden ser utilizados indistintamente. Aquí hay una manera fácil de confirmar que:
Array.instance_method(:map) == Array.instance_method(:collect)
=> true
He buscado en Google y tengo opiniones parciales / contradictorias: ¿existe realmente alguna diferencia entre hacer un map y hacer una collect en una matriz en Ruby / Rails?
Los docs no parecen sugerir nada, pero ¿existen diferencias en el método o el rendimiento?
Hice una prueba de referencia para intentar responder esta pregunta, luego encontré esta publicación, así que aquí están mis conclusiones (que difieren ligeramente de las otras respuestas)
Aquí está el código de referencia:
require ''benchmark''
h = { abc: ''hello'', ''another_key'' => 123, 4567 => ''third'' }
a = 1..10
many = 500_000
Benchmark.bm do |b|
GC.start
b.report("hash keys collect") do
many.times do
h.keys.collect(&:to_s)
end
end
GC.start
b.report("hash keys map") do
many.times do
h.keys.map(&:to_s)
end
end
GC.start
b.report("array collect") do
many.times do
a.collect(&:to_s)
end
end
GC.start
b.report("array map") do
many.times do
a.map(&:to_s)
end
end
end
Y los resultados que obtuve fueron:
user system total real
hash keys collect 0.540000 0.000000 0.540000 ( 0.570994)
hash keys map 0.500000 0.010000 0.510000 ( 0.517126)
array collect 1.670000 0.020000 1.690000 ( 1.731233)
array map 1.680000 0.020000 1.700000 ( 1.744398)
Tal vez un alias no es gratis?
No hay diferencia, de hecho, el map se implementa en C como rb_ary_collect y enum_collect (por ejemplo, hay una diferencia entre el map en una matriz y en cualquier otra enumeración, pero no hay diferencia entre el map y la collect ).
¿Por qué tanto el map como la collect existen en Ruby? La función de map tiene muchas convenciones de nombres en diferentes idiomas. Wikipedia proporciona una visión general :
La función de mapa se originó en lenguajes de programación funcionales, pero hoy en día se admite (o puede definirse) en muchos lenguajes de procedimiento, orientados a objetos y de paradigma múltiple: en la biblioteca de plantillas estándar de C ++, se denomina
transform, en C # (3.0) '' En la biblioteca LINQ, se proporciona como un método de extensión llamadoSelect. El mapa también es una operación de uso frecuente en lenguajes de alto nivel como Perl, Python y Ruby; La operación se llamamapen los tres idiomas. También se proporciona un alias decollectpara el mapa en Ruby (de Smalltalk) [énfasis mío]. Common Lisp proporciona una familia de funciones tipo mapa; el que corresponde al comportamiento descrito aquí se llamamapcar(-car indica el acceso mediante la operación CAR).
Ruby proporciona un alias para que los programadores del mundo de Smalltalk se sientan más cómodos.
¿Por qué hay una implementación diferente para arrays y enumeraciones? Una enumeración es una estructura de iteración generalizada, lo que significa que no hay forma en que Ruby pueda predecir lo que puede ser el siguiente elemento (puede definir enumeraciones infinitas, vea Prime para un ejemplo). Por lo tanto, debe llamar a una función para obtener cada elemento sucesivo (normalmente este será el método de each ).
Las matrices son la colección más común, por lo que es razonable optimizar su rendimiento. Dado que Ruby sabe mucho acerca de cómo funcionan los arreglos, no tiene que llamar a each pero solo puede usar la manipulación simple de punteros, que es significativamente más rápida.
Existen optimizaciones similares para varios métodos de Array como zip o count .
Ruby alias el método Array # map to Array # collect; Se pueden usar indistintamente. (Ruby Monk)
En otras palabras, el mismo código fuente:
static VALUE
rb_ary_collect(VALUE ary)
{
long i;
VALUE collect;
RETURN_SIZED_ENUMERATOR(ary, 0, 0, ary_enum_length);
collect = rb_ary_new2(RARRAY_LEN(ary));
for (i = 0; i < RARRAY_LEN(ary); i++) {
rb_ary_push(collect, rb_yield(RARRAY_AREF(ary, i)));
}
return collect;
}
Me han dicho que son lo mismo.
En realidad están documentados en el mismo lugar bajo ruby-doc.org:
http://www.ruby-doc.org/core/classes/Array.html#M000249
- ary.collect {| item | bloque} → new_ary
- ary.map {| item | bloque} → new_ary
- ary.collect → an_enumerator
- ary.map → an_enumerator
Invoca el bloque una vez por cada elemento del yo. Crea una nueva matriz que contiene los valores devueltos por el bloque. Véase también Enumerable # collect.
Si no se da ningún bloque, se devuelve un enumerador.
a = [ "a", "b", "c", "d" ] a.collect {|x| x + "!" } #=> ["a!", "b!", "c!", "d!"] a #=> ["a", "b", "c", "d"]