2011-01-15 9 views

Respuesta

685

Si utiliza ruby ​​1.8.7 o 1.9, puede utilizar el hecho de que los métodos de iterador como each_with_index, cuando se llama sin un bloque, devuelve un objeto Enumerator, que puede llamar a Enumerable métodos como map en. Por lo que puede hacer:

arr.each_with_index.map { |x,i| [x, i+2] } 

En 1.8.6 se puede hacer:

require 'enumerator' 
arr.enum_for(:each_with_index).map { |x,i| [x, i+2] } 
+0

Gracias! ¿Podría darme un puntero a la documentación para '.each_with_index.map'? –

+0

En este caso 'map' es una función de qué? –

+1

@Misha: 'map' es un método de' Enumerable' como siempre. 'each_with_index', cuando se llama sin un bloque, devuelve un objeto' Enumerator' (en 1.8.7+), que mezcla en 'Enumerable', por lo que puede llamar' map', 'select',' reject', etc. al igual que en una matriz, hash, rango, etc. – sepp2k

9

Aquí hay dos opciones más para 1.8.6 (o 1.9) sin necesidad de utilizar empadronador:

# Fun with functional 
arr = ('a'..'g').to_a 
arr.zip((2..(arr.length+2)).to_a) 
#=> [["a", 2], ["b", 3], ["c", 4], ["d", 5], ["e", 6], ["f", 7], ["g", 8]] 

# The simplest 
n = 1 
arr.map{ |c| [c, n+=1 ] } 
#=> [["a", 2], ["b", 3], ["c", 4], ["d", 5], ["e", 6], ["f", 7], ["g", 8]] 
14

lo largo de la parte superior de ofuscación:

arr = ('a'..'g').to_a 
indexes = arr.each_index.map(&2.method(:+)) 
arr.zip(indexes) 
+7

me gusta, el código oscuro siempre es divertido de mantener. –

+9

¡Andrew debe tener una gran seguridad laboral! :) –

203

Rubí> = 1.9.3 tiene 012.. Para convertir la matriz a un empadronador, utilice Object#to_enum o Array#map, lo que se siente más declarativa a usted:

[:a, :b, :c].map.with_index(2).to_a 
#=> [[:a, 2], [:b, 3], [:c, 4]] 
+7

¡Esta es la mejor respuesta hasta ahora! –

+3

Solución muy elegante, gracias! – dolzenko

+8

Creo que esta es la mejor respuesta, ¡ya que funcionará con el mapa! 'foo = ['d'] * 5; foo.map! .with_index {| x, i | x * i}; foo # => ["", "d", "dd", "ddd", "dddd"] ' –

3
a = [1, 2, 3] 
p [a, (2...a.size+2).to_a].transpose 
2
module Enumerable 
    def map_with_index(&block) 
    i = 0 
    self.map { |val| 
     val = block.call(val, i) 
     i += 1 
     val 
    } 
    end 
end 

["foo", "bar"].map_with_index {|item, index| [item, index] } => [["foo", 0], ["bar", 1]] 
+3

¡OMG! ¿Leíste las otras respuestas? 'map.with_index' ya existe en ruby. ¿Por qué sugieren reabrir la clase enumerable y agregar algo que ya existe? – nathanvda

+0

Esta podría ser una forma más fácil de usar para 1.8.6 y 1.8.7 (sí, algunos de nosotros todavía la usan) en lugar de tener que usar cosas más extrañas como 'each_with_index.map', etc. e incluso aquellos de nosotros en versiones más nuevas podríamos prefiero tener que usar map.with_index FWIW :) – rogerdpack

1

A menudo hago esto:

arr = ["a", "b", "c"] 

(0...arr.length).map do |int| 
    [arr[int], int + 2] 
end 

#=> [["a", 2], ["b", 3], ["c", 4]] 

En lugar de directamente interactuando sobre los elementos de la matriz, está iterando sobre un rango de enteros y usándolos como los índices para recuperar los elementos de la matriz.

+1

Si lees las otras respuestas, espero que ahora te des cuenta de que hay mejores enfoques. Así que no estoy seguro de por qué necesita agregar esto. – nathanvda

+0

¡Si la respuesta de Andrew Grimm merece diez votos, entonces esta merece al menos uno! –

+0

Creo que deberías lanzar un bucle for por si acaso;) –

0

Un divertido, pero es demasiado inútil para hacer esto:

az = ('a'..'z').to_a 
azz = az.map{|e| [e, az.index(e)+2]} 
+0

¿Por qué odias? Es una forma funcional de hacer esto Y hasta digo que es una manera tonta de lograr los resultados. – Automatico

+0

la llamada a #index significa que ahora es un bucle O (N^2) también por qué el +2? :) – rogerdpack

+1

Mientras escribo 'Una manera divertida, pero inútil'. '+ 2' es para crear la salida que OP solicita – Automatico

71

En Ruby 1.9.3 hay un método llamado chainable with_index que puede ser encadenado a mapear.

Por ejemplo: array.map.with_index { |item, index| ... }

6

que siempre han disfrutado de la sintaxis de este estilo:

a = [1, 2, 3, 4] 
a.each_with_index.map { |el, index| el + index } 
# => [1, 3, 5, 7] 

Invocando each_with_index le consigue un empadronador puede asignar fácilmente sobre con su índice disponible.

+2

¿cómo es esta forma diferente [la respuesta, dada casi 5 años antes que la suya] (http://stackoverflow.com/a/4697573/1772830)? –

Cuestiones relacionadas