Как вытащить наибольшее значение из массива и удвоить его значение

Итак, у меня есть код, который дает мне комбинации. Я хотел бы найти наибольшее значение driver_points из каждой комбинации, а затем удвоить его значение.

Вот мой код в настоящее время:

     # DRIVER AND TEAM ARRAYS
     driver_points = { "john" => 18.1, "mike" => 19.3, "paul" => 15.6, "mark" => 1.1 }
     driver_price = { "john" => 4.0, "mike" => 5.0, "paul" => 6.0, "mark" => 2.1 }
     team_points = { "cowboys" => 20.1, "bears" => 19.3, "lions" => 15.6, "united" => 2.8 }
     team_price = { "cowboys" => 1.0, "bears" => 2.0, "lions" => 3.0, "united" => 2.4 }

    # DEFINE VARIABLE AND TARGET
     teams = team_price.keys
     drivers = driver_price.keys
     target = 13.5

    # CREATE METHOD TO SUM BOTH PRICES AND POINTS FOR GIVEN COMBINATION
    def add_up(combo, ht, hd)
      t, d = combo
      ht[t] + hd.values_at(*d).sum
    end

    # ALL POSSIBLE COMBINATIONS OF TEAM AND DRIVERS
    all_driver_combos = drivers.combination(3).to_a
    all_combos = teams.product(all_driver_combos)

    # SHOW ALL COMBOS WHERE SUM DOES NOT EXCEED TARGET
    valid_combos = all_combos.select do |c|
      add_up(c, team_price, driver_price) <= target
    end

    # SORT VALID COMBOS BY SUM OF POINTS FOR EACH ELEMENT
    ordered = valid_combos.sort_by do |c|
      -add_up(c, team_points, driver_points)
    end

    #OUTPUT
    @combo = ordered.map do |c|
      { c.join(" ")=>{ price: add_up(c, team_price, driver_price),
             points: add_up(c, team_points, driver_points).round(2) } }
    end

Который в настоящее время выводит комбинации (1 команда и 3 гонщика) на основе целевого значения, но отсортированные по наивысшим баллам:

[{"cowboys john mike mark"=>{:price=>12.1, :points=>58.6}}, {"bears john mike mark"=>{:price=>13.1, :points=>57.8}}, {"cowboys john paul mark"=>{:price=>13.1, :points=>54.9}}, {"united john mike mark"=>{:price=>13.5, :points=>41.3}}]

Я хотел бы иметь возможность найти самого высокого водителя на основе самых высоких точек driver_points из каждой комбинации и удвоить значение его очков.

Например, в моей первой выведенной комбинации: {"cowboys john mike mark"=>{:price=>12.1, :points=>58.6}}

Я хочу иметь возможность найти гонщика с наибольшим количеством очков из трех - это будет один из Джона, Майка и Марка, поскольку я не хочу включать команду. Ответ - Майк, так как у него 19,3 очка. А затем удвойте очки водителя Майка, что должно обновить сумму :points=>. Давая новый общий балл 77,9. Кроме того, я хотел бы иметь возможность перемещать драйвер с наивысшими точками в начало комбинации драйверов для целей стилизации в представлении.

Итак, мой желаемый результат таков:

Команда Двойной Комбо Цена Точки ковбои Майк Джон Марк 12.1 77,9

🤔 А знаете ли вы, что...
Этот веб-фреймворк использует концепцию 'конвенции выше конфигураций' (Convention over Configuration), что упрощает разработку.


76
1

Ответ:

Решено

Вы вычислили

valid_combos
  #=> [["cowboys", ["john", "mike", "mark"]],
  #    ["cowboys", ["john", "paul", "mark"]],
  #    ["bears",   ["john", "mike", "mark"]],
  #    ["united",  ["john", "mike", "mark"]]]

Рассмотрите комбо

c = ["cowboys", ["john", "mike", "mark"]]
        20.1      18.1    19.3     1.1
   

где очки команды для "cowboys" и очки водителя для каждого из трех водителей в этой комбинации показаны выше. (Кто-то должен поговорить с Марком.)

Общее количество очков за эту комбинацию равно

add_up(c, team_points, driver_points)
  #=> 58.6

К этому мы хотим добавить 19.3 очки, которые являются очками водителя для "Mike", поскольку у него больше всего очков среди трех водителей комбинации:

58.6 + 19.3
  #=> 77.9

Мы можем сделать это в коде следующим образом.

def add_dbl(combo, team_points, driver_points)
  t, ds = combo
  dmax = ds.max_by { |d| driver_points[d] }
  driver_points[dmax] + add_up(combo, team_points, driver_points)
end

Для комбинации c, определенной выше,

add_dbl(c, team_points, driver_points)
  #=> 77.9

как и ожидалось. Теперь мы можем использовать add_dbl вместо add_up для сортировки комбинаций.

ordered = valid_combos.sort_by do |c|
  -add_dbl(c, team_points, driver_points)
end
  #=> [["cowboys", ["john", "mike", "mark"]],
  #    ["bears", ["john", "mike", "mark"]],
  #    ["cowboys", ["john", "paul", "mark"]],
  #    ["united", ["john", "mike", "mark"]]]

Следующий код переставляет водителей таким образом, чтобы водитель с наибольшим количеством очков водителей отображался первым в каждом массиве водителей в ordered.

ordered.each do |_t,ds|
  imax = ds.each_index.max_by { |i| driver_points[ds[i]] }  
  ds.unshift(ds.delete_at(imax))
end
  #=> [["cowboys", ["mike", "john", "mark"]],
  #    ["bears", ["mike", "john", "mark"]],
  #    ["cowboys", ["john", "paul", "mark"]],
  #    ["united", ["mike", "john", "mark"]]]

См. Array#each_index , Enumerable#max_by , Array#unshift и Array#delete_at . Обратите внимание, что Array#each возвращает свой получатель (ordered), но мы модифицируем этот массив.


Чтобы просто отсортировать драйверы от самой высокой до самой низкой точки драйвера, измените приведенное выше выражение следующим образом.

ordered.each do |_t,ds|
  ds.sort_by! { |d| -driver_points[d] }
end
  #=> [["cowboys", ["mike", "john", "mark"]],
  #    ["bears", ["mike", "john", "mark"]],
  #    ["cowboys", ["john", "paul", "mark"]],
  #    ["united", ["mike", "john", "mark"]]]

По совпадению, эти массивы драйверов ничем не отличаются от приведенных выше.

Смотрите Массив#sort_by!.