tamaño array ruby arrays map collect

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 llamado Select . 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 llama map en los tres idiomas. También se proporciona un alias de collect para 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 llama mapcar (-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; }

http://ruby-doc.org/core-2.2.0/Array.html#method-i-map


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"]