Как найти среднее из массива?
Если у меня есть массив:
[0,4,8,2,5,0,2,6]
Усреднение дало бы мне 3,375.
ruby-on-rails
ruby
рехнувшийся
источник
источник
Ответы:
Попробуй это:
Обратите внимание
.to_f
, что вы хотите, чтобы избежать каких-либо проблем из целочисленного деления. Вы также можете сделать:Вы можете определить его как часть,
Array
как предложил другой комментатор, но вам нужно избегать целочисленного деления, иначе ваши результаты будут неправильными. Кроме того, это обычно не применимо к каждому возможному типу элемента (очевидно, что среднее значение имеет смысл только для вещей, которые можно усреднить). Но если вы хотите пойти по этому пути, используйте это:Если вы еще не видели
inject
, это не так волшебно, как может показаться. Он перебирает каждый элемент, а затем применяет к нему значение аккумулятора. Затем аккумулятор передается следующему элементу. В этом случае наш аккумулятор - это просто целое число, которое отражает сумму всех предыдущих элементов.Редактировать: комментатор Дейв Рэй предложил хорошее улучшение.
Изменить: предложение комментатора Гленн Джекман, используя
arr.inject(:+).to_f
, тоже хорошо, но, возможно, слишком умным, если вы не знаете, что происходит. Это:+
символ; при передаче для внедрения он применяет метод, названный символом (в данном случае, операцию сложения), к каждому элементу по отношению к значению аккумулятора.источник
arr.inject(0.0) { |sum,el| sum + el } / arr.size
.inject
интерфейса, упомянутая в документации.to_proc
Оператор&
.Array#inject
это излишне. Просто используйте#sum
. Напримерarr.sum.to_f / arr.size
Версия этого, который не использует
instance_eval
, будет:источник
instance_eval
позволяет запустить код, указав толькоa
один раз, чтобы он мог быть связан с другими командами. Т.е.random_average = Array.new(10) { rand(10) }.instance_eval { reduce(:+) / size.to_f }
вместоrandom = Array.new(10) { rand(10) }; random_average = random.reduce(:+) / random.size
self
внутри этого блока, вы столкнетесь с проблемами.)instance_eval
Больше для метапрограммирования или DSL.Я считаю, что самый простой ответ
источник
reduce
это методEnumerable
миксина, который используетсяArray
. И несмотря на его название, я согласен с @ShuWu ... если вы не используете Rails, который реализуетsum
.Я надеялся на Math.average (значения), но не такая удача.
источник
sum
метод, так это , кажется, правильный ответ после 6 лет, достойные награды Nostradamus.Версии Ruby> = 2.4 имеют метод Enumerable # sum .
А чтобы получить среднее значение с плавающей запятой, вы можете использовать Integer # fdiv
Для более старых версий:
источник
Некоторый сравнительный анализ лучших решений (в порядке наиболее эффективных):
Большой массив:
Малые массивы:
источник
источник
nil
а не 0?Позвольте мне внести в конкуренцию нечто, что решает проблему деления на ноль:
Однако я должен признать, что «try» является помощником Rails. Но вы можете легко решить это:
Кстати: я думаю, что это правильно, что среднее значение пустого списка равно нулю. Среднее ничего - ничто, а не 0. Так что это ожидаемое поведение. Однако, если вы измените на:
результат для пустых массивов не будет исключением, как я ожидал, но вместо этого он возвращает NaN ... Я никогда раньше такого не видел в Ruby. ;-) Кажется, это особенное поведение класса Float ...
источник
что мне не нравится в принятом решении
в том, что он не работает чисто функционально. нам нужна переменная arr для вычисления arr.size в конце.
чтобы решить это чисто функционально, нам нужно отслеживать два значения: сумму всех элементов и количество элементов.
Santhosh улучшил это решение: вместо аргумента r, являющегося массивом, мы могли бы использовать деструктуризацию, чтобы сразу выделить его на две переменные
если вы хотите посмотреть, как это работает, добавьте несколько мест:
Мы могли бы также использовать структуру вместо массива, чтобы содержать сумму и количество, но затем мы должны сначала объявить структуру:
источник
end.method
в ruby, спасибо за это!arr.inject([0.0,0]) { |(sum, size), el| [ sum + el, size + 1 ] }.inject(:/)
Для общественного развлечения, еще одно решение:
источник
На этом компьютере нет рубина, но что-то в этом смысле должно работать:
источник
Добавить
Array#average
.Я делал то же самое довольно часто, поэтому я подумал, что было бы разумно просто расширить
Array
класс с помощью простогоaverage
методом. Он не работает ни для чего, кроме массива чисел, таких как целые числа или числа с плавающей запятой или десятичные числа, но это удобно, когда вы используете его правильно.Я использую Ruby on Rails, поэтому я поместил это в,
config/initializers/array.rb
но вы можете разместить его в любом месте, которое включено в загрузку и т. Д.config/initializers/array.rb
источник
источник
Решает деление на ноль, целочисленное деление и легко читается. Может быть легко изменено, если вы выберете пустой массив, возвращающий 0.
Мне тоже нравится этот вариант, но он немного более объемный.
источник
источник
Этот метод может быть полезен.
источник
Без необходимости повторять массив (например, идеально подходит для однострочников):
источник
Коротко, но с использованием переменной экземпляра
источник
a_size = nil; [1,2].tap { |a| a_size = a.size }.inject(:+).to_f/a_size
а не создать переменную экземпляра.Вы можете попробовать что-то вроде следующего:
источник