在python中,当存在等级平局时,选择列表中第n个最低/最高成员的可扩展方法



参加黑客等级挑战,感觉自己真的成功了。需要选择列表中倒数第二的成员,如果出现平局,则返回两个成员。我是这样做的:

if __name__ == '__main__':
names = []
scores = []
names_scores = []
for _ in range(int(input())):
name = input()
score = float(input())
names.append(name)
scores.append(score)
names_scores.append([name, score])
def second_smallest(numbers):
m1 = m2 = float('inf')
for x in numbers:
if x <= m1:
m1, m2 = x, m1
elif x < m2:
m2 = x
return m2

second_smallest_number = second_smallest(set(scores))
second_lowest_name_score = filter(lambda x: x[1] == second_smallest_number, names_scores)
second_lowest_names = [item[0] for item in second_lowest_name_score]
second_lowest_names.sort()
if len(second_lowest_names) == 1:
print(second_lowest_names[0])
else:
print(second_lowest_names[0] + "n" + second_lowest_names[1])

我的问题是,即使我"通过了"我需要为每一个平局数写一行新的if语句。我想知道一种方法,无论有多少个关系,它都可以扩展。我理解我可以pandasrank(),但想知道如何使用标准库

做到这一点

使用itertools.groupby对相同的分数进行分组:

>>> from itertools import groupby
>>> def second_lowest(scores):
...     ranks = (g for _, g in groupby(sorted(scores)))
...     first = list(next(ranks))
...     if len(first) >= 2:
...         return first  # second lowest is also tied for first lowest
...     return list(next(ranks))  # otherwise return second lowest rank
...
>>> second_lowest([1, 1, 1, 2, 2, 3])
[1, 1, 1]
>>> second_lowest([1, 2, 2, 2, 2, 2, 3, 3])
[2, 2, 2, 2, 2]

对于更通用的函数(即获得第n个最低),您可以保留迭代过的单个分数的计数,并返回第n个分数所在的组。

我们最后做的是:

if __name__ == '__main__':
scores = []
names_scores = []
for _ in range(int(input())):
name = input()
score = float(input())
scores.append(score)
names_scores.append([name, score])
from collections import Counter
scores = sorted(Counter(scores).items())
second_lowest_score = scores[1][0]
names = sorted([name_score[0] for name_score in names_scores if name_score[1] == second_lowest_score])
print("n".join(names))

最新更新