Необходимо простое объяснение метода инъекции

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

Я смотрю на этот код, но мой мозг не регистрирует, как число 10 может стать результатом. Кто-нибудь подумает, что здесь происходит?

Ответ 1

Вы можете думать о первом блочном аргументе в качестве аккумулятора: результат каждого запуска блока хранится в накопителе, а затем передается следующему исполнению блока. В случае кода, показанного выше, вы по умолчанию используете аккумулятор, результат, равный 0. Каждый запуск блока добавляет заданный номер к текущему итогу, а затем сохраняет результат обратно в аккумулятор. Следующий вызов блока имеет это новое значение, добавляет к нему, сохраняет его снова и повторяет.

В конце процесса впрыск возвращает накопитель, который в этом случае является суммой всех значений в массиве или 10.

Вот еще один простой пример создания хэша из массива объектов, с помощью строкового представления:

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

В этом случае мы по умолчанию используем наш аккумулятор для пустого хэша, а затем заполняем его каждый раз, когда выполняется блок. Обратите внимание, что мы должны вернуть хеш в качестве последней строки блока, потому что результат блока будет сохранен обратно в аккумуляторе.

Ответ 2

inject принимает значение для начала (0 в вашем примере) и блок, и он запускает этот блок один раз для каждого элемента списка.

  • На первой итерации он передает значение, которое вы указали как начальное значение, и первый элемент списка, и сохраняет значение, возвращаемое вашим блоком (в данном случае result + element).
  • Затем он снова запускает блок, передавая результат первой итерации в качестве первого аргумента, а второй элемент из списка - вторым аргументом, снова сохраняя результат.
  • Это продолжается до тех пор, пока не уничтожит все элементы списка.

Самый простой способ объяснить это может состоять в том, чтобы показать, как каждый шаг работает для вашего примера; это мнимый набор шагов, показывающий, как этот результат можно оценить:

[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

Ответ 3

Синтаксис для метода инъекции выглядит следующим образом:

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

Пусть решается приведенный выше пример, т.е.

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

который дает 10 в качестве выхода.

Итак, перед запуском давайте посмотрим, какие значения хранятся в каждой переменной:

result = 0 Нуль пришел из инъекции (значения), которая равна 0

element = 1 Это первый элемент массива.

Окей!!! Итак, давайте начнем понимать приведенный выше пример

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

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

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

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

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

Здесь значения Bold-Italic - это выборка элементов из массива, а просто значения Полужирный - это результирующие значения.

Я надеюсь, что вы поймете работу метода #inject #ruby.

Ответ 4

Код выполняет итерацию по четырем элементам массива и добавляет предыдущий результат к текущему элементу:

  • 1 + 2 = 3
  • 3 + 3 = 6
  • 6 + 4 = 10

Ответ 5

Что они сказали, но обратите внимание также, что вам не всегда нужно указывать "начальное значение":

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

совпадает с

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

Попробуй, я подожду.

Когда аргумент не передается для ввода, первые два элемента передаются в первую итерацию. В приведенном выше примере результат равен 1, а элемент равен 2 в первый раз, поэтому в блок делается меньше вызовов.

Ответ 6

Число, которое вы помещаете внутри вашего() инъекции, представляет собой начальное место, оно может быть 0 или 1000. Внутри труб у вас есть два держателя | x, y |. x = то, что у вас было внутри объекта .inject('x'), а secound представляет каждую итерацию вашего объекта.

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

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

Ответ 7

В приложении применяется блок

result + element

для каждого элемента массива. Для следующего элемента ( "элемент" ) значение, возвращаемое из блока, является "результатом". То, как вы его назвали (с параметром), "результат" начинается со значения этого параметра. Таким образом, эффект заключается в добавлении элементов вверх.

Ответ 8

TL;DR; inject отличается от map одним важным способом: inject возвращает значение последнего выполнения блока, тогда как map возвращает массив, который он повторил.

Более того значение каждого исполнения блока передается в следующее выполнение через первый параметр (result в этом случае), и вы можете инициализировать это значение (часть (0)).

Ваш приведенный выше пример можно записать с помощью map следующим образом:

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

Тот же эффект, но inject более краткий.

Часто вы обнаружите, что назначение выполняется в блоке map, тогда как оценка выполняется в блоке inject.

Какой метод вы выбираете, зависит от области действия, которую вы хотите использовать для result. Когда не использовать, это будет примерно так:

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

Вы можете быть похожими на всех: "Посмотри, я только что объединил все в одну строку", но вы также временно выделили память для x как переменную нуля, которая не была необходимой, поскольку у вас уже было result до работать с.

Ответ 9

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

эквивалентно следующему:

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

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

На простом английском языке вы проходите (итерацию) через этот массив ([1,2,3,4]). Вы будете проходить через этот массив 4 раза, потому что есть 4 элемента (1, 2, 3 и 4). Инъекционный метод имеет 1 аргумент (число 0), и вы добавите этот аргумент в 1-й элемент (0 + 1. Это равно 1). 1 сохраняется в "результате". Затем вы добавляете этот результат (который равен 1) к следующему элементу (1 + 2. Это 3). В результате это будет сохранено. Продолжайте движение: 3 + 3 равно 6. И, наконец, 6 + 4 равно 10.

Ответ 11

Этот код не позволяет не передавать начальное значение, но может помочь объяснить, что происходит.

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

Начните здесь, а затем просмотрите все методы, которые принимают блоки. http://ruby-doc.org/core-2.3.3/Enumerable.html#method-i-inject

Является ли это блоком, который вас смущает или почему у вас есть значение в методе? Хороший вопрос. Что такое оператор?

result.+

Что начинается с?

#inject(0)

Можем ли мы это сделать?

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

Это работает?

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

Вы видите, что я основываюсь на идее, что она просто суммирует все элементы массива и дает число в заметке, которую вы видите в документах.

Вы всегда можете сделать это

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

чтобы увидеть, как перечислимый массив проходит через. Это основная идея.

Это просто инъекция или сокращение дает вам записку или аккумулятор, который отправляется.

Мы могли бы попытаться получить результат

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

но ничего не возвращается, так что это действует так же, как и раньше

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

в блоке инспектора элементов.

Ответ 13

Существует другая форма метода .inject(). Это очень полезно. [4,5].inject(&: +) Это добавит весь элемент области

Ответ 14

Это просто reduce или fold, если вы знакомы с другими языками.

Ответ 15

Это простое и довольно простое для понимания объяснение:

Забудьте о "начальном значении", так как в начале оно несколько сбивает с толку.

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

Вы можете понять вышесказанное следующим образом: я ввожу "машину добавления" между 1,2,3,4. Это означает, что это 1 ♫ 2 ♫ 3 ♫ 4, а ♫ - это сложение, поэтому оно равно 1 + 2 + 3 + 4 и равно 10.

Вы можете вставить между ними +:

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

и это похоже на вставку + между 1,2,3,4, делая его 1 + 2 + 3 + 4 и равным 10. :+ - это Ruby-способ определения + в форма символа.

Это довольно легко понять и интуитивно понятно. И если вы хотите проанализировать, как это работает, шаг за шагом, это как: взять 1 и 2, а затем добавить их, а когда у вас есть результат, сначала сохранить его (который равен 3), а теперь, следующий хранится значение 3 и элемент массива 3 проходят через процесс a + b, который равен 6, и теперь сохраняют это значение, а теперь 6 и 4 проходят процесс a + b и равен 10. По сути, вы выполняете

((1 + 2) + 3) + 4

и равно 10. "Начальное значение" 0 - это просто "основа" для начала. Во многих случаях вам это не нужно. Представьте, если вам нужно 1 * 2 * 3 * 4, и это

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

и это сделано. Вам не нужно "начальное значение" 1, чтобы умножить все это на 1.

Ответ 16

То же самое:

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