Значит ли инъекция, начинающаяся с 0, то же самое, что и сумма? - PullRequest
2 голосов
/ 08 октября 2019

Я новичок в ruby ​​и собирался, хотя кусок кода

scope_value = {"tickets_scope"=>"1", "changes_scope"=>"8", "solutions_scope"=>"15"}
scope_value.values.map { |i| 2** i.to_i }.inject(0, :|)

Я понял,

scope_value.values.map {|i| 2** i.to_i }.sum

делает то же самое, что и

С точки зрения функциональности обе строки кода не делают одно и то же. Есть ли какое-то преимущество в использовании суммы перед другими с точки зрения производительности.

Ответы [ 2 ]

5 голосов
/ 08 октября 2019

С точки зрения функциональности обе строки кода не делают одно и то же.

Да, эти два фрагмента дают одинаковые результаты.

инъекция, начинающаяся с 0, означает то же самое, что и сумма

Нет, совсем нет. На самом деле, 0 здесь не имеет значения. Вы можете опустить его и получить тот же результат.

scope_value.values.map { |i| 2** i.to_i }.inject(:|)

Операции в этих двух фрагментах очень разные. Они дают одинаковый результат только из-за особой формы ваших данных. Что означает, что «каждое число имеет только один установленный бит, и никакие два числа не могут иметь одинаковый установленный бит». Нарушьте это правило и увидите, что результаты расходятся.


Кстати, до того, как у нас было .sum, мы использовали его для эмуляции с .inject(:+). Это делает то же самое (при использовании целочисленных массивов)

1 голос
/ 09 октября 2019

Они действительно означают то же самое, но только , потому что вы не используете Float s и только , потому что у вас нет Range.

По крайней мере, в некоторых версиях некоторых реализаций Ruby sum имеет некоторые оптимизации и специализации, которые inject и + не могут иметь, потому что они гораздо более общие. Например, в YARV текущая реализация различных вариантов sum составляет почти 200 строк и включает в себя следующие оптимизации

  • Enumerable#sum, когдаприменяется к Enumerable<Float>, использует алгоритм Kahan-Babuška с компенсацией с компенсацией с компенсацией для предотвращения накопления ошибок точности с плавающей запятой при суммировании
  • Range#sum, когдаПрименительно к Range<Integer> используется известная формула закрытой формы: (end - start + 1) * (end + start) / 2 конец, таким образом, не зависит от размера диапазона, любое зависит только от длины используемых чисел

Цена, которую мы платим за это, заключается в том, что sum может игнорировать зашифрованные версии each или +.

...