2013-10-13 5 views
1

Каков подходящий метод для получения суммы двух наибольших значений в массиве с использованием Ruby?Как суммировать наибольшие два элемента в массиве

Я знаю array.sort и array.max и inject(:+), но я не знаю, как их сочетать.

+0

Задавая это важно показать усилия к решению этой проблемы, в противном случае это выглядит, как вы хотите, чтобы мы написали код для вас. Прочитайте «[ask]», включая связанные страницы, и «[Сколько усилий ожидается от пользователей Stack Overflow?] (Http://meta.stackoverflow.com/q/261592/128421)». Также важно выбрать ответ, который решил проблему: http://meta.stackexchange.com/questions/5234/how-does-accepting-an-answer-work –

ответ

2
[1,2,3,4].sort[-2..-1].inject(:+) 

Если вы ищете более эффективное решение, вы будете лучше с этим один:

[1,2,3,4].inject([0, 0]) do |largest, el| 
    if largest[0] < el 
    largest[1] = largest[0] 
    largest[0] = el 
    elsif largest[1] < el 
    largest[1] = el 
    end 
    largest 
end.inject(:+) 

Если вы знакомы со сложностью алгоритма, чем вы можете увидеть, что первый из них является nlogn до n^2, в зависимости от алгоритма сортировки Ruby, где второе решение равно n, когда оно проходит через массив один раз.

+0

Я обновил свой ответ с более эффективным решением. –

+2

«эффективный» не является хорошим словом, чтобы описать разницу. Первая короче, понятна и понятна, и работает примерно в 50 раз быстрее, чем вторая. Это также идиоматический Ruby при попытке выполнить эту задачу. –

+1

В дополнение к точке @ theTinMan, асимптотические сравнения часто несущественны. Тебе нужно протестировать. В частности, когда один метод оптимизирован в C (например, 'sort'), а другой нет, первый часто бывает быстрее, иногда на милю. –

4
[9, 4, 5, 1].sort.last(2).sum 
=> 14 
+1

Прохладный. Не знал о последствиях с аргументами. 'sum', хотя это метод Rails. Он задал вопрос как RoR, но спросил решение Ruby. Неясно, нужен ли ему ванильный раствор. –

+0

Я добавил тесты для тестирования различных решений. См. Http://stackoverflow.com/a/38809082/128421 –

+0

Ruby получит 'Enumerable # sum' в [версии 2.4] (http://www.blackbytes.info/ruby-version-changes/). –

1

Вы могли бы попробовать что-то вроде этого

array = [13, 2, 21, 36, 4, 9] 

array.reverse.first(2).reduce(:+) 

В этом методе мы обратной сортировки массива, который сортирует его от самого высокого до самого низкого. Это ставит наибольшие числа сначала в массиве. reduce метод возвращает сумму этих чисел. В этом случае, сумма 36 и 21 57.

57 
+0

Поскольку это вопрос с Rails, 'sum' будет предпочтительнее, чем' reduce (: +) '. –

+0

'array.reverse.first (2) .reduce (: +) # => 13'. Вы не сортируете массив вообще. Всегда хорошо проверять вашу работу. –

6

Я бы сильно благоприятствуют тем проще и быстрее:

array.max(2).reduce(:+) 

Сортировка ненужно, достаточно для сканирования массива обновляющий макс -разрыв размера K. Используя Array#max(K), вы достигаете асимптотической сложности времени O (N x log (K)) по сравнению с O (N x log (N)) сортировки.

+0

Отличное использование 'max'. –

1

Это всегда хорошо иметь несколько тестов, чтобы увидеть, что это самый быстрый способ сделать что-то:

require 'active_support/core_ext/enumerable' 
require 'fruity' 

ARRAY = (0..1000).to_a.shuffle 

compare do 

    adriano { ARRAY.max(2).reduce(:+)  } 
    mori { ARRAY.sort.last(2).sum  } 
    edgars { ARRAY.sort[-2..-1].inject(:+) } 

end 


# >> Running each test 64 times. Test will take about 1 second. 
# >> adriano is faster than edgars by 50.0% ± 10.0% 
# >> edgars is similar to mori 
Смежные вопросы