Necesidad de una explicación simple de la inyectan método

[1, 2, 3, 4].inject(0) { |result, element| result + element } # => 10

Estoy buscando en este código, pero mi cerebro no registra cómo el número 10 puede ser el resultado. Alguien importaría explicar lo que está pasando aquí?

InformationsquelleAutor | 2009-04-02

16 Kommentare

  1. 199

    Se puede pensar en el primer bloque argumento como un acumulador: el resultado de cada ejecución del bloque se almacena en el acumulador y, a continuación, pasar a la siguiente ejecución del bloque. En el caso de que el código que se muestra arriba, se están incumpliendo el acumulador, en consecuencia, a 0. Cada ejecución del bloque agrega el número asignado a la corriente total y, a continuación, almacena el resultado en el acumulador. El siguiente bloque de que se llame a este nuevo valor, se le añade, la almacena de nuevo, y repite.

    Al final del proceso, inyectar devuelve el acumulador, que en este caso es la suma de todos los valores en la matriz, o 10.

    He aquí otro ejemplo sencillo para crear un hash a partir de un conjunto de objetos, la forma adecuada por su representación de cadena:

    [1,"a",Object.new,:hi].inject({}) do |hash, item|
      hash[item.to_s] = item
      hash
    end

    En este caso, se están incumpliendo nuestro acumulador a un hash vacío, luego rellenarlo cada vez que el bloque se ejecuta. Aviso debemos devolver el hash como la última línea del bloque, debido a que el resultado del bloque se almacenan en el acumulador.

    • Gracias por la gran explicación y el hash ejemplo – que realmente hizo claro.
    • gran explicación, sin embargo, en el ejemplo dado por el OP, lo que se devuelve (como el hash es en su ejemplo). Termina con el resultado + explicación y debe tener un valor de retorno, sí?
    • el result + explanation es tanto la transformación en el acumulador y el valor de retorno. Es la última línea en el bloque de lo que es una forma implícita de retorno.
  2. 84

    inject toma un valor para empezar (el 0 en tu ejemplo), y a una cuadra, y es que el bloque se ejecuta una vez para cada elemento de la lista.

    1. En la primera iteración, se pasa el valor que usted proporciona como valor de partida, y el primer elemento de la lista, y se guarda el valor que su bloque devuelto (en este caso result + element).
    2. A continuación, ejecuta el bloque de nuevo, pasando el resultado de la primera iteración, como primer argumento, y el segundo elemento de la lista como segundo argumento, vuelve a guardar el resultado.
    3. Continúa de esta manera hasta que se ha consumido todos los elementos de la lista.

    La forma más fácil de explicar que esto puede ser para mostrar cómo cada paso funciona, por tu ejemplo; este es un imaginario conjunto de pasos que muestran cómo este resultado podría ser evaluados:

    [1, 2, 3, 4].inject(0) { |result, element| result + element }
    [2, 3, 4].inject(0 + 1) { |result, element| result + element }
    [3, 4].inject((0 + 1) + 2) { |result, element| result + element }
    [4].inject(((0 + 1) + 2) + 3) { |result, element| result + element }
    [].inject((((0 + 1) + 2) + 3) + 4) { |result, element| result + element }
    (((0 + 1) + 2) + 3) + 4
    10
    • Gracias por la escritura de los pasos. Esto me ayudó mucho. Aunque estaba un poco confundido acerca de si usted quiere decir que el siguiente diagrama es cómo inyectar el método es implementado por debajo en términos de lo que se pasan como argumentos a inyectar.
    • El diagrama a continuación se basa en cómo se puede ser implementado; no es necesariamente aplican exactamente de esta manera. Por eso he dicho que es un imaginario conjunto de pasos; se muestra la estructura básica, pero no la exacta aplicación.
    • La mejor expresión visual de inyectar que he visto nunca.
  3. 27

    La sintaxis para inyectar el método es como sigue:

    inject (value_initial) { |result_memo, object| block }

    Vamos a resolver el ejemplo anterior es decir

    [1, 2, 3, 4].inject(0) { |result, element| result + element }

    que da la 10 como la salida.

    Así que, antes de empezar vamos a ver cuáles son los valores almacenados en cada una de las variables:

    resultado = 0 El cero vino de inyectar(valor) que es 0

    elemento = 1 es el primer elemento de la matriz.

    Okey!!! Así que, vamos a empezar a entender el ejemplo anterior

    Paso :1 [1, 2, 3, 4].inject(0) { |0, 1| 0 + 1 }

    Paso :2 [1, 2, 3, 4].inject(0) { |1, 2| 1 + 2 }

    Paso :3 [1, 2, 3, 4].inject(0) { |3, 3| 3 + 3 }

    Paso :4 [1, 2, 3, 4].inject(0) { |6, 4| 6 + 4 }

    Paso :5 [1, 2, 3, 4].inject(0) { |10, Now no elements left in the array, so it'll return 10 from this step| }

    Aquí Negrita-Cursiva los valores son elementos de captura de la matriz y el simplemente Negrita los valores son los valores resultantes.

    Espero que usted entienda el trabajo de la #inject método de la #ruby.

  4. 18

    El código itera a través de los cuatro elementos dentro de la matriz y añade el resultado anterior para el elemento actual:

    • 1 + 2 = 3
    • 3 + 3 = 6
    • 6 + 4 = 10
  5. 15

    Lo que dijo, pero tenga en cuenta también que no siempre es necesario dar un «valor inicial»:

    [1, 2, 3, 4].inject(0) { |result, element| result + element } # => 10

    es el mismo que

    [1, 2, 3, 4].inject { |result, element| result + element } # => 10

    Intentar, voy a esperar.

    Cuando no hay argumento que se pasa a inyectar, la primera dos elementos se aprobó en la primera iteración. En el ejemplo anterior, el resultado es 1 y el elemento es 2 la primera vez, así que uno menos se realiza una llamada al bloque.

  6. 14

    El número que usted coloca dentro de su () de inyectar representa un punto de partida, podría ser 0 o 1000.
    Dentro de los tubos tiene dos marcadores de posición |x, y|. x = ¿qué número cada vez tenía dentro de el .inyectar(‘x’), y el secound representa cada iteración de su objeto.

    [1, 2, 3, 4].inject(5) { |result, element| result + element } # => 15

    1 + 5 = 6
    2 + 6 = 8
    3 + 8 = 11
    11 + 4 = 15

  7. 6

    Inyectar aplica el bloque

    result + element

    a cada elemento de la matriz. Para el siguiente elemento («elemento»), el valor devuelto desde el bloque de «resultado». La forma en la que has llamado (con un parámetro), «resultado» se inicia con el valor de ese parámetro. Por lo que el efecto de la adición de los elementos de seguridad.

  8. 6

    tldr; inject difiere de map en un aspecto importante: inject devuelve el valor de la última ejecución del bloque, mientras que map devuelve la matriz es iterado.

    Más de que el valor de cada uno de los bloques de ejecución pasa a la siguiente ejecución a través del primer parámetro (result en este caso) y se puede inicializar ese valor (el (0) parte).

    Su ejemplo de arriba puede ser escrito utilizando map como este:

    result = 0 # initialize result
    [1, 2, 3, 4].map { |element| result += element }
    # result => 10

    Mismo efecto pero inject es más conciso.

    Usted encontrará a menudo una tarea que sucede en el map bloque, mientras que una evaluación que sucede en el inject bloque.

    El método que usted elija depende del alcance que usted desea para result. Cuando a no uso sería algo como esto:

    result = [1, 2, 3, 4].inject(0) { |x, element| x + element }

    Podría ser como todos, «Lookie a mí, yo simplemente la combinación de todos en una sola línea,» pero también temporalmente la memoria asignada para x como un cero de la variable que no era necesario puesto que ya había result a trabajar con.

  9. 4
    [1, 2, 3, 4].inject(0) { |result, element| result + element } # => 10

    es equivalente a la siguiente:

    def my_function(r, e)
      r+e
    end
    
    a = [1, 2, 3, 4]
    result = 0
    
    a.each do |value|
      result = my_function(result, value)
    end
  10. 3

    [1, 2, 3, 4].inject(0) { |result, element| result + element } # => 10

    En la llanura inglés, usted va a través de (iteración) a través de esta matriz ([1,2,3,4]). Usted va a iterar a través de esta matriz 4 veces, porque hay 4 elementos (1, 2, 3 y 4). El método de inyectar ha 1 argumento (el número 0), y usted tendrá que añadir que el argumento para el 1 de elemento (0 + 1. Esto es igual a 1). 1 se guarda en el «resultado». A continuación, puede agregar que el resultado (que es 1) para el siguiente elemento (1 + 2. Esta es la 3). Este ahora se guardarán como el resultado. Seguir adelante: 3 + 3 es igual a 6. Y por último, 6 + 4 es igual a 10.

  11. 2

    Este código no permite la posibilidad de no aprobar un valor de partida, pero puede ayudar a explicar lo que está pasando.

    def incomplete_inject(enumerable, result)
      enumerable.each do |item|
        result = yield(result, item)
      end
      result
    end
    
    incomplete_inject([1,2,3,4], 0) {|result, item| result + item} # => 10
  12. 1

    Empezar aquí y, a continuación, la revisión de todos los métodos que toman los bloques.
    http://ruby-doc.org/core-2.3.3/Enumerable.html#method-i-inject

    Es el bloque que confunde o por qué tiene un valor en el método?
    Buena pregunta, aunque. ¿Cuál es el método de operador de allí?

    result.+

    Lo que hace es empezar como?

    #inject(0)

    Podemos hacer esto?

    [1, 2, 3, 4].inject(0) { |result, element| result.+ element }

    Hace este trabajo?

    [1, 2, 3, 4].inject() { |result = 0, element| result.+ element }

    Ves que estoy construyendo en la idea de que simplemente suma todos los elementos de la matriz y de los rendimientos de un número en la nota que ver en la documentación.

    Siempre se puede hacer este

     [1, 2, 3, 4].each { |element| p element }

    para ver el enumerable de la matriz de llegar a afirmar a través de. Esa es la idea básica.

    Es sólo que se inyectan o reducir darle un memo o un acumulador que se envía.

    Podríamos tratar de conseguir un resultado

    [1, 2, 3, 4].each { |result = 0, element| result + element }

    pero nada viene de vuelta por lo que este solo actúa de la misma como antes

    [1, 2, 3, 4].each { |result = 0, element| p result + element }

    en el elemento inspector de bloque.

  13. 0

    Este es un simple y bastante fácil de entender explicación:

    Olvidarse de «valor inicial» ya que es algo confuso al principio.

    > [1,2,3,4].inject{|a,b| a+b}
    => 10

    Puede entender lo anterior como: yo soy la inyección de una «máquina de sumar» entre 1,2,3,4. Es decir, 1 ♫ 2 ♫ 3 ♫ 4 y ♫ es una máquina de sumar, de modo que es el mismo que 1 + 2 + 3 + 4 y es 10.

    Realidad se puede inyectar un + entre ellos:

    > [1,2,3,4].inject(:+)
    => 10

    y es como, inyectar una + entre 1,2,3,4, lo que es 1 + 2 + 3 + 4 y es 10. El :+ es Ruby forma de especificar + en la forma de un símbolo.

    Esto es bastante fácil de entender e intuitiva. Y si usted desea analizar cómo funciona paso a paso, es como: tomar 1 y 2, y ahora agregar a ellos, y cuando se tiene un resultado, de la tienda es el primero (que es 3), y ahora, la próxima es el valor almacenado 3 y el elemento de la matriz 3 de ir a través de los a + b proceso, que es de 6, y ahora, este valor se almacena, y ahora de 6 y 4 ir a través de los a + b proceso, y es de 10. Básicamente se está haciendo

    ((1 + 2) + 3) + 4

    y es de 10. El «valor inicial» 0 es sólo una «base» para comenzar con. En muchos de los casos, usted no lo necesita. Imagínese si usted necesita 1 * 2 * 3 * 4 y es

    [1,2,3,4].inject(:*)
    => 24

    y es hecho. Usted no necesita un «valor inicial» de 1 para multiplicar la totalidad de la cosa con 1.

  14. -1

    Es el mismo que este:

    [1,2,3,4].inject(:+)
    => 10
    • Si bien esto es un hecho, que no responde a la pregunta.

Kommentieren Sie den Artikel

Bitte geben Sie Ihren Kommentar ein!
Bitte geben Sie hier Ihren Namen ein

Pruebas en línea