2
Here's another approach that, while somewhat complex, has been designed for efficiency. The method uses the following steps.
这是另一种方法,尽管有些复杂,但它的设计是为了提高效率。该方法使用以下步骤。
- Convert each
Team
instance to to an array containing the instance and the three-element array on which the inexpensive sort is to be done.
将每个Team实例转换为包含实例和三元素数组的数组,在该数组上进行廉价排序。
- Use Enumerable#sort_by to sort the arrays by the three-element arrays.
使用Enumerable#sort_by按三元素数组对数组进行排序。
- Use Enumerable#chunk to group the two-element arrays that have equal three-element arrays.
使用Enumerable#chunk对具有相同三元素数组的两元素数组进行分组。
- Map each chunked array element to the
Team
instance in the two-element array.
将每个chunked数组元素映射到两元素数组中的Team实例。
- Use Enumerable#flat_map to map each chunked group of
Team
instances after it has been sorted by the method a_beat_b(a, b)
(unless the group contains only one team, of course).
使用Enumerable#flat_map在按方法a_beat_b(a,b)对每个已分块的Team实例组进行排序后映射(当然,除非该组只包含一个团队)。
Code
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
Example
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)
]
#=> [#,
# #,
# #,
# #,
# #]
def a_beat_b(a, b)
a.name.size <=> b.name.size
end
sort_em(teams)
#=> [#,
# #,
# #,
# #,
# #]
Explanation
The steps are as follows.
步骤如下。
a = teams.map { |t| [t, [t.points, t.goal_dif, t.goals]] }
#=> [[#,
# [233, 25, 130]],
# [#,
# [233, 18, 105]],
# [#,
# [233, 25, 130]],
# [#,
# [160, 12, 105]],
# [#,
# [233, 18, 105]]]
b = a.sort_by(&:last)
#=> [[#,
# [160, 12, 105]],
# [#,
# [233, 18, 105]],
# [#,
# [233, 18, 105]],
# [#,
# [233, 25, 130]],
# [#,
# [233, 25, 130]]
# ]
c = b.chunk(&:last)
#=> #:each>
To see what values are generated by the enumerator c
we can convert it to an array.
要查看枚举器c生成的值,我们可以将其转换为数组。
c.to_a
#=> [[[160, 12, 105],
# [[#,
# [160, 12, 105]
# ]
# ]
# ],
# [[233, 18, 105],
# [[#,
# [233, 18, 105]
# ],
# [#,
# [233, 18, 105]
# ]
# ],
# [[233, 25, 130],
# [[#,
# [233, 25, 130]
# ],
# [#,
# [233, 25, 130]
# ]
# ]
# ]
# ]
d = c.map { |_,tied_teams| tied_teams.map(&:first) }
#=> [[#],
# [#,
# #
# ],
# [#,
# #
# ]
# ]
d.flat_map { |tied_teams| (tied_teams.size == 1) ?
tied_teams.first : tied_teams.sort { |a,b| a_beat_b(a, b) } }
#=> [#,
# #,
# #,
# #,
# #
# ]