将不同的散列值切换到一个组合数组中,并执行一个计算,对第一个数组进行排序-Rubyonrails

cnwbcb6i  于 2023-01-30  发布在  Ruby
关注(0)|答案(1)|浏览(90)

我有几个数组包含相同的值,但有不同的键与它们相关联。在本例中,我有 * Teams * 和 * Drivers * 的名称,它们有一个相关联的 * Price * 和 * Points * 值。我为每个数组使用了4,但其中可以有任何数字,都是小数。

# DRIVER AND TEAM ARRAYS
driver_points = { "john" => 20.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 }

我已经将 * driver_price * 和 * team_price * 散列转换为一个数组,它可以为我提供所有小于或等于目标值的组合。条件是它只能包含1支球队和3名车手。现在我想按最高点对这些价格组合进行排名。因此,我希望有一种方法,在我当前的组合中,我可以用等价的 * points * 值替换每个键。求和点,然后排名的组合点。我也希望,而不是我的组合包含数字的关键是使用代替。
这是我当前的代码(给我目标的所有组合)。还有一行在底部,这是合计每个组合。

# ALL COMBINATIONS OF DRIVERS AND TEAMS BASED ON BUDGET AND ARRAY
team = team_price.values.permutation(1).to_a
driver = driver_price.values.permutation(3).to_a
target = 13.5
array = team.product(driver)
res = array.select {|i| i.map(&:sum).sum <= target}.compact
t1 = res.map {|i| i[0]}
d2 = res.map {|i| i[1].flatten.sort}
combo = t1.zip(d2).uniq
full_combo = combo.flatten.each_slice(4).to_a

# TOTAL COST OF COMBINATION
total_cost = combo.map {|budget| budget.map(&:sum).sum}

# OUTPUT
@test1 = full_combo, total_cost

输出(所有价格组合和合计组合):
[[[1.0, 2.1, 4.0, 5.0], [1.0, 2.1, 4.0, 6.0], [2.0, 2.1, 4.0, 5.0], [2.4, 2.1, 4.0, 5.0]], [12.1, 13.1, 13.1, 13.5]]
我想对这些组合进行排名,但是要用等价的 * 点数 * 值。所以希望我可以切换点数,把它加起来,然后根据这个从高到低排列组合,同时显示键而不是值。所以类似这样的东西:
1.将当前组合转换为等效键:
[[cowboys, mark, john, mike], [cowboys, mark, john, paul], [bears, mark, john, mike], [united, mark, john, mike]]
1.使用此函数切换 * points * 散列值并对每个组合求和:
[[60.6], [56.9], [59.8], [43.4]]
1.然后使用点数和来排列每个组合。理想输出:
| 组合|总价|总分|
| - ------|- ------|- ------|
| 牛仔马克约翰麦克|十二、一|六十点六|
| 熊,马克,约翰,迈克|十三、一|五十九点八|
| 牛仔,马克,约翰,保罗|十三、一|五十六点九|
| 曼联,马克,约翰,迈克|十三点五|四十三点四|

bgibtngc

bgibtngc1#

我们已知散列值team_pricedriver_priceteam_pointsdriver_points以及 * 组合 * 的最高价格,该组合由一个车队和三个车手组成:

target = 13.5

我们首先需要控制车队和车手的变量。
x一个一个一个一个x一个一个二个x
展望未来,我们将需要对给定组合的价格和点数求和,因此创建一个这样做的方法是有意义的。

def add_up(combo, ht, hd)
  t, d = combo
  ht[t] + hd.values_at(*d).sum
end

例如,如果,

combo = ["cowboys", ["john", "mike", "paul"]]

那么这个组合的总价格是

add_up(combo, team_price, driver_price)
  #=> 16.0

请参见哈希#values_at和数组#sum。
我们需要计算一个价格总和不超过target的所有组合的数组,首先计算三个驱动因素的所有组合。

all_driver_combos = drivers.combination(3).to_a
  #=> [["john", "mike", "paul"], ["john", "mike", "mark"],
  #    ["john", "paul", "mark"], ["mike", "paul", "mark"]]

请参见阵列编号组合。
接下来构建所有组合。

all_combos = teams.product(all_driver_combos)
  #=> [["cowboys", ["john", "mike", "paul"]],
  #    ["cowboys", ["john", "mike", "mark"]],
  #    ["cowboys", ["john", "paul", "mark"]],
  #    ["cowboys", ["mike", "paul", "mark"]],
  #    ["bears", ["john", "mike", "paul"]],
  #    ["bears", ["john", "mike", "mark"]],
  #    ["bears", ["john", "paul", "mark"]],
  #    ["bears", ["mike", "paul", "mark"]],
  #    ["lions", ["john", "mike", "paul"]],
  #    ["lions", ["john", "mike", "mark"]],
  #    ["lions", ["john", "paul", "mark"]],
  #    ["lions", ["mike", "paul", "mark"]],
  #    ["united", ["john", "mike", "paul"]],
  #    ["united", ["john", "mike", "mark"]],
  #    ["united", ["john", "paul", "mark"]],
  #    ["united", ["mike", "paul", "mark"]]]

参见阵列#产品。
接下来,从all_combos中抽取价格总和不超过target的那些。

valid_combos = all_combos.select do |c|
  add_up(c, team_price, driver_price) <= target
end
  #=> [["cowboys", ["john", "mike", "mark"]],
  #    ["cowboys", ["john", "paul", "mark"]],
  #    ["bears", ["john", "mike", "mark"]],
  #    ["united", ["john", "mike", "mark"]]]

如果需要,我们可以替换all_driver_combos和链all_combos

valid_combos = teams.product(drivers.combination(3).to_a)
                    .select do |c|
                       add_up(c, team_price, driver_price)<=target
                     end

最后,我们希望通过valid_combos中每个元素的点数之和对valid_combos进行排序。

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

请参见可枚举的#sort_by。
请注意,我已经对add_up返回的值取反,以便从最大到最小排序。

ordered = valid_combos.sort_by do |c|
  add_up(c, team_points, driver_points)
end.reverse

我们可以按如下方式检查ordered的每个元素的价格和点数的总和。

ordered.map do |c|
  { c=>{ price: add_up(c, team_price, driver_price),
         points: add_up(c, team_points, driver_points) } }  
end
  #=> [{["cowboys", ["john", "mike", "mark"]]=>
  #        {:price=>12.1, :points=>60.6}},
  #    {["bears", ["john", "mike", "mark"]]=>
  #        {:price=>13.1, :points=>59.8}},
  #    {["cowboys", ["john", "paul", "mark"]]=>
  #        {:price=>13.1, :points=>56.9}},
  #    {["united", ["john", "mike", "mark"]]=>
  #        {:price=>13.5, :points=>43.3}}]

相关问题