我有以下資料庫列 team_a_set_1, team_a_set_2, team_a_set_3, team_a_set_4, team_a_set_5, team_b_set_1, team_b_set_2, team_b_set_3, team_b_set_4, team_b_set_5. 我正在使用這些列來存盤5組網球比賽的結果。
現在我試圖找出team a和team b之間誰是贏家。誰贏得了最多的局數,誰就是贏家。我的代碼看起來大致是這樣的
def find_winner
team_a_win_count=0
team_b_win_count =0
if team_a_set_1.present? & & team_b_set_1.present?
if team_a_set_1 > team_b_set_1
team_a_win_count = team_a_win_count 1
elsif team_b_set_1 > team_a_set_1
team_b_win_count = team_b_win_count 1
結束。
end
if team_a_set_2.present? & & team_b_set_2.present?
if team_a_set_2 > team_b_set_2
team_a_win_count = team_a_win_count 1
elsif team_b_set_2 > team_a_set_2
team_b_win_count = team_b_win_count 1
結束。
end
if team_a_set_3.present? & & team_b_set_3.present?
if team_a_set_3 > team_b_set_3
team_a_win_count = team_a_win_count 1
elsif team_b_set_3 > team_a_set_3
team_b_win_count = team_b_win_count 1
結束。
end
if team_a_set_4.present? & & team_b_set_4.present?
if team_a_set_4 > team_b_set_4
team_a_win_count = team_a_win_count 1
elsif team_b_set_4 > team_a_set_4
team_b_win_count = team_b_win_count 1
結束。
end
if team_a_set_5.present? & & team_b_set_5.present?
if team_a_set_5 > team_b_set_5
team_a_win_count = team_a_win_count 1
elsif team_b_set_5 > team_a_set_5
team_b_win_count = team_b_win_count 1
結束。
end
if team_a_win_count > team_b_win_count
放置'Team A won'。
elsif team_b_win_count > team_a_win_count
放置'Team B won'。
else
放置'draw''B隊獲勝
end
end。
如你所見,我在if陳述句中重復了5次相同的邏輯。我想重構這段代碼,這樣我就不用重復同樣的事情5次了。我試過這樣的方法,但沒有成功
1.upto(5) do |n|
if "team_a_set_#{n}"/span>. 目前? && "team_b_set_#{n}"/span>.目前?
if "team_a_set_#{n}" > "team_b_set_#{n}" # this is not working because it's comparing string.
team_a_win_count = team_a_win_count 1
elsif "team_b_set_#{n}"/span> > "team_a_set_#{n}"/span>
team_b_win_count = team_b_win_count 1"
end
end
end end
那么我怎樣才能重構這段代碼,使我不必寫5次if陳述句呢?
更新:根據大家的建議,我最終重新設計了我的資料庫。現在,我將集合存盤在哈希中。現在一切看起來都很好,很干凈。
uj5u.com熱心網友回復:
這里的答案很可能是對資料進行更好的建模。
class Game < ApplicationRecord
belongs_to :player_a, class_name: 'Player'
belongs_to :player_b, class_name: 'Player'。
has_many :game_sets[/span]。
end
# rails g model game_set game:belong_to player_a_score:integer player_b_score:integer。
class GameSet < ApplicationRecord
belongs_to:game
end。
這設定了一個簡單的一對多,而不是有N個列。這讓你可以通過選擇聚合體來簡單地統計行數:
Game.select(
'games.*'。
'SUM(
SELECT 1 FROM gamesets gs WHERE gs.game_id = games.id AND gs.player_a_score > gs.player_b_score
) AS player_a_wins'。
'SUM(
SELECT 1 FROM gamesets gs WHERE gs.game_id = games.id AND gs.player_b_score > gs.player_a_score
) AS player_b_wins'。
'SUM(
SELECT 1 FROM gamesets gs WHERE gs.game_id = games.id AND gs.player_b_score = gs.player_a_score
) AS draws'
)
你也可以直接在game_sets表中快取結果:
class GameSet < ApplicationRecord
belongs_to : game
belongs_to :winner。
class_name: 'Player'。
optional: true # nil for draws.
end
還有一長串更有效的方法來獲得聚合,比如在Postgres上使用FILTER或者橫向連接。你還應該考慮將游戲的結果直接保存在游戲表中,以獲得更好的讀取性能。
uj5u.com熱心網友回復:
正如我之前提到的,當你發現自己在變數名上添加了一個整數后綴時,請想我應該使用一個陣列。。同樣地,如果你發現自己使用了字串前綴或后綴,你應該使用哈希值。
這段代碼的寫法,很難遵循邏輯,在沒有了解更多的情況下,很難提出具體的建議,但是,如果你能以如下格式獲得資料:
games = [
{
'a'/span> => [12, 34, 56, 78, 90] 。
'b' => [21, 43, 65, 87, 9] 。
},
{
'a' => [1, 2, 3, 4, 5] 。
'b' => [5, 4, 2, 2, 1] 。
},
]
games.each_index do |g|
游戲 = 游戲[g]
teams = game.key
wins = Hash[team.map {|t| [t, 0]})
game[team[0]].each_index do |i|]
winner = game[team[0]][i] > game[team[1]] [i] ? 0 : 1
wins[team[winner]] = 1 1
結束。
將"游戲的贏家#{g}。#{teams[wins[teams[0]] > wins[teams[1] ]? ? 0 : 1] }"
結束。
你將擁有能夠處理任意球隊之間任意數量的比賽的優勢。此外,你將不必改變代碼來處理不同的游戲/球隊的參考方式。
擁有以下資料庫列
team_a_set_1,team_a_set_2,team_a_set_3,team_a_set_4。team_a_set_5,team_b_set_1,team_b_set_2,team_b_set_3,team_b_set_4,team_b_set_5.
而這確實是你的問題。資料庫的設計并不恰當,無法真正做到這類事情。事實上,如果表GAMES有以下列。game, set, team, score, 你就不需要寫任何 Ruby 來做這個了。
uj5u.com熱心網友回復:
在不了解你的資料結構和停留在方法使用上的情況下,你可以做這樣的事情:
def find_winner
team_counter = {a_team: 0, b_team: 0}.
# 如果有更多關于你的資料模型的資訊,可以再次改進。
集合 = [...
[team_a_set_1, team_b_set_1],
[team_a_set_2, team_b_set_2],
[team_a_set_3, team_b_set_3]。
[team_a_set_4, team_b_set_4]。
[team_a_set_5, team_b_set_5] 。
]
sets.each do |set|
set_winner_team = set_winner_team?(a_team: set[0],b_team: set[1] )
team_counter = increase_set_winner_counter(set_winner_team, team_counter)
結束。
winner_congrats(team_counter)
end
私有
def set_winner_team? (a_team: nil,b_team: nil)
return unless a_team.present? & & b_team.present?
return :a_team if a_team > b_team
:b_team ifb_team > a_team
end
def increase_set_winner_counter(set_winner_team, team_counter)
return team_counter unless set_winner_team
team_counter.tap do ||
team_counter[set_winner_team] =1
end
end end
def winner_congrats(team_counter)
if team_counter[:a_team] > team_counter[:b_team]
puts 'Team A won'/span>
elsif team_counter[:a_team] < team_counter[:b_team]
puts 'Team B won'>
else
放置'抽簽'。
end
end。
Ps:我使用了以set_開頭的方法名,這不是一個好的做法,但我這樣做是為了明確。請找到更好的名字。
Ps2:未經測驗的代碼,可能會有一些錯誤
。轉載請註明出處,本文鏈接:https://www.uj5u.com/ruanti/322764.html
標籤:
