Đây là một cách tiếp cận khác, trong khi hơi phức tạp, được thiết kế để có hiệu quả. Phương pháp này sử dụng các bước sau.
- Chuyển đổi từng mảng
Team
thành một mảng chứa thể hiện và mảng ba phần tử mà sắp xếp không tốn kém.
- Sử dụng Enumerable#sort_by để sắp xếp mảng theo mảng ba phần tử.
- Sử dụng Enumerable#chunk để nhóm các mảng hai phần tử có mảng ba phần tử bằng nhau.
- Ánh xạ từng phần tử mảng vào ví dụ
Team
trong mảng hai phần tử.
- Sử dụng Enumerable#flat_map để ánh xạ từng nhóm chunked
Team
trường hợp sau khi được sắp xếp theo phương pháp a_beat_b(a, b)
(trừ khi nhóm chỉ chứa một nhóm).
Mã
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
Ví dụ
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>]
Giải thích
Các bước thực hiện như sau.
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>
Để xem giá trị nào được tạo bởi điều tra c
, chúng tôi có thể chuyển đổi giá trị đó thành một mảng.
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>
# ]
gì thực hiện của bạn của 'a_beat_b' trông như thế nào? Ý của bạn là gì khi bạn nói "không thể lấy mã đúng"? – Matt
'a_beat_b' hoạt động như một' <=> ', trả về 1 nếu đội A đã đánh bại B giải đấu này. 0 nếu hòa, và -1 nếu B thắng. Mã cho 'Array.sort' giống như thế này,' teams.sort (| a, b | [a.points, a.goals_dif, a.goals] <=> [b.points, b.goals_dif, b.mục tiêu]) 'Không biết phải đặt chức năng của tôi ở đâu. Sẽ chỉnh sửa nó. –
'Array # sort' là câu trả lời đúng. Bạn nên kiểm tra xem các mảng có giống nhau không và sau đó sử dụng điều kiện 'a_beat_b' để thực hiện so sánh đắt tiền hơn. Nếu không thấy * cách * bạn đã cố gắng thực hiện 'Array # sort', chúng tôi thực sự không thể giúp bạn. – meagar