Oto inne podejście, że choć trochę skomplikowane, został zaprojektowany dla wydajności. Metoda wykorzystuje następujące kroki.
- konwersji każdego
Team
na przykład na tablicy zawierającej tablicę wystąpienie i trzech elementów w którym tani sortowania do wykonania.
- Użyj Enumerable#sort_by, aby posortować tablice według tablic trzyelementowych.
- Skorzystaj z Enumerable#chunk, aby pogrupować dwuelementowe macierze, które mają równe, trój elementowe tablice.
- Mapuj każdy element tablicy z kawałkami na instancję
Team
w tablicy dwuelementowej.
- Użyj Enumerable#flat_map do odwzorowania każdej porcji grupy instancji
Team
po posortowaniu według metody a_beat_b(a, b)
(chyba że grupa zawiera tylko jeden zespół, oczywiście).
kod
def sort_em(teams)
teams.map { |t| [t, [t.points, t.goal_dif, t.goals]] }.
sort_by(&:last).
chunk(&:last).
map { |_,tied_teams| tied_teams.map(&:first) }.
flat_map { |tied_teams| (tied_teams.size == 1) ?
tied_teams.first : tied_teams.sort { |a,b| a_beat_b(a, b) } }
end
Przykład
class Team
attr_reader :name, :points, :goal_dif, :goals
def initialize(name, points, goal_dif, goals)
@name, @points, @goal_dif, @goals = name, points, goal_dif, goals
end
end
teams = [Team.new("bluebirds", 233, 25, 130),
Team.new("eagles", 233, 18, 105),
Team.new("jays", 233, 25, 130),
Team.new("owls", 160, 12, 105),
Team.new("sparrows", 233, 18, 105)
]
#=> [#<Team:0x007ff2f900e5a8 @name="bluebirds", @points=233, @goal_dif=25, @goals=130>,
# #<Team:0x007ff2f900e530 @name="eagles", @points=233, @goal_dif=18, @goals=105>,
# #<Team:0x007ff2f900e4b8 @name="jays", @points=233, @goal_dif=25, @goals=130>,
# #<Team:0x007ff2f900e440 @name="owls", @points=160, @goal_dif=12, @goals=105>,
# #<Team:0x007ff2f900e3c8 @name="sparrows", @points=233, @goal_dif=18, @goals=105>]
def a_beat_b(a, b)
a.name.size <=> b.name.size
end
sort_em(teams)
#=> [#<Team:0x007ff2fa845630 @name="owls", @points=160, @goal_dif=12, @goals=105>,
# #<Team:0x007ff2fa845720 @name="eagles", @points=233, @goal_dif=18, @goals=105>,
# #<Team:0x007ff2fa8455b8 @name="sparrows", @points=233, @goal_dif=18, @goals=105>,
# #<Team:0x007ff2fa8456a8 @name="jays", @points=233, @goal_dif=25, @goals=130>,
# #<Team:0x007ff2fa8457e8 @name="bluebirds", @points=233, @goal_dif=25, @goals=130>]
Objaśnienie
Kroki są następujące.
a = teams.map { |t| [t, [t.points, t.goal_dif, t.goals]] }
#=> [[#<Team:0x007ff2fa8457e8 @name="bluebirds", @points=233, @goal_dif=25, @goals=130>,
# [233, 25, 130]],
# [#<Team:0x007ff2fa845720 @name="eagles", @points=233, @goal_dif=18, @goals=105>,
# [233, 18, 105]],
# [#<Team:0x007ff2fa8456a8 @name="jays", @points=233, @goal_dif=25, @goals=130>,
# [233, 25, 130]],
# [#<Team:0x007ff2fa845630 @name="owls", @points=160, @goal_dif=12, @goals=105>,
# [160, 12, 105]],
# [#<Team:0x007ff2fa8455b8 @name="sparrows", @points=233, @goal_dif=18, @goals=105>,
# [233, 18, 105]]]
b = a.sort_by(&:last)
#=> [[#<Team:0x007ff2fa845630 @name="owls", @points=160, @goal_dif=12, @goals=105>,
# [160, 12, 105]],
# [#<Team:0x007ff2fa845720 @name="eagles", @points=233, @goal_dif=18, @goals=105>,
# [233, 18, 105]],
# [#<Team:0x007ff2fa8455b8 @name="sparrows", @points=233, @goal_dif=18, @goals=105>,
# [233, 18, 105]],
# [#<Team:0x007ff2fa8457e8 @name="bluebirds", @points=233, @goal_dif=25, @goals=130>,
# [233, 25, 130]],
# [#<Team:0x007ff2fa8456a8 @name="jays", @points=233, @goal_dif=25, @goals=130>,
# [233, 25, 130]]
# ]
c = b.chunk(&:last)
#=> #<Enumerator: #<Enumerator::Generator:0x007ff2fa81dc20>:each>
Aby zobaczyć, jakie wartości są generowane przez moduł wyliczający c
możemy przekonwertować go na tablicy.
c.to_a
#=> [[[160, 12, 105],
# [[#<Team:0x007ff2fa845630 @name="owls",@points=160,@goal_dif=12,@goals=105>,
# [160, 12, 105]
# ]
# ]
# ],
# [[233, 18, 105],
# [[#<Team:0x007ff2fa845720 @name="eagles",@points=233,@goal_dif=18,@goals=105>,
# [233, 18, 105]
# ],
# [#<Team:0x007ff2fa8455b8 @name="sparrows",@points=233,@goal_dif=18,@goals=105>,
# [233, 18, 105]
# ]
# ],
# [[233, 25, 130],
# [[#<Team:0x007ff2fa8457e8 @name="bluebirds",@points=233,@goal_dif=25,@goals=130>,
# [233, 25, 130]
# ],
# [#<Team:0x007ff2fa8456a8 @name="jays", @points=233,@goal_dif=25,@goals=130>,
# [233, 25, 130]
# ]
# ]
# ]
# ]
d = c.map { |_,tied_teams| tied_teams.map(&:first) }
#=> [[#<Team:0x007ff2fa845630 @name="owls", @points=160, @goal_dif=12, @goals=105>],
# [#<Team:0x007ff2fa845720 @name="eagles", @points=233, @goal_dif=18, @goals=105>,
# #<Team:0x007ff2fa8455b8 @name="sparrows", @points=233, @goal_dif=18, @goals=105>
# ],
# [#<Team:0x007ff2fa8457e8 @name="bluebirds", @points=233, @goal_dif=25, @goals=130>,
# #<Team:0x007ff2fa8456a8 @name="jays", @points=233, @goal_dif=25, @goals=130>
# ]
# ]
d.flat_map { |tied_teams| (tied_teams.size == 1) ?
tied_teams.first : tied_teams.sort { |a,b| a_beat_b(a, b) } }
#=> [#<Team:0x007ff2fa845630 @name="owls", @points=160, @goal_dif=12, @goals=105>,
# #<Team:0x007ff2fa845720 @name="eagles", @points=233, @goal_dif=18, @goals=105>,
# #<Team:0x007ff2fa8455b8 @name="sparrows", @points=233, @goal_dif=18, @goals=105>,
# #<Team:0x007ff2fa8456a8 @name="jays", @points=233, @goal_dif=25, @goals=130>,
# #<Team:0x007ff2fa8457e8 @name="bluebirds", @points=233, @goal_dif=25, @goals=130>
# ]
Co twoja realizacja 'a_beat_b' wyglądać? Co masz na myśli, mówiąc, że "nie udało ci się uzyskać prawidłowego kodu"? – Matt
'a_beat_b' działa jak' <=> ', zwraca 1, jeśli drużyna A pokonała B w tym turnieju. 0 w przypadku remisu i -1, jeśli wygrał B. Kod dla 'Array.sort' był taki:' teams.sort (| a, b | [a.points, a.goals_dif, a.goals] <=> [b.points, b.goals_dif, b.cele]) 'Nie wiedział, gdzie umieścić moją funkcję. Dokona edycji. –
"Tablica # sort" jest właściwą odpowiedzią. Powinieneś sprawdzić, czy tablice są identyczne, a następnie warunkowo użyć 'a_beat_b', aby wykonać droższe porównanie. Nie widząc * jak * próbowałeś zaimplementować 'Array # sort', tak naprawdę nie możemy ci pomóc. – meagar