如何将这个浮点数列表按升序排列?

3

我已经能够从CSV文件中导入每个人的3个分数(或数字),并计算出每个人的三个分数的平均值,但接下来我需要按从高到低的顺序对输出中显示的平均值列表进行排序。我已经搜索了所有地方,尝试过的每种方法都出现了“Float”错误。

from collections import defaultdict, deque
with open("highscores.csv", "r+")as file:
    file.seek(0)
    scores = file.readlines()
user_scores = defaultdict(lambda:deque(maxlen=3))
for line in scores:
    name, score = line.rstrip('\n').split(',')
    score = int(score)
    user_scores[name].append(score)

for name in user_scores:
    avg = (user_scores[name])
    x = sorted(avg)
    avg2 = sum(x) / float(len(x))
    print(name, avg2)

输出:

Odis 22.0
Vance 20.0
John 26.0
Marinda 25.0
Shenita 18.0
Marquitta 24.0
Concepcion 17.0
Robby 23.0
Valda 19.0
Ernesto 21.0
Jack 5.0

我的CSV文件长这样:

Jack    4
Jack    5
Jack    6
Concepcion  7
Shenita 8
Valda   9
Vance   10
Ernesto 11
Odis    12
Robby   13
Marquitta   14
Marinda 15
John    16
Concepcion  17
Shenita 18
Valda   19
Vance   20
Ernesto 21
Odis    22
Robby   23
Marquitta   24
Marinda 25
John    26
Concepcion  27
Shenita 28
Valda   29
Vance   30
Ernesto 31
Odis    32
Robby   33
Marquitta   34
Marinda 35
John    36

2
你已经接近成功了。创建一个新的字典,包含每个名称及其平均值,并对其进行排序:https://dev59.com/EHRB5IYBdhLWcg3weHLx - Brent Washburne
3个回答

3

不需要对平均值进行排序 - 毕竟这些是单个人的分数,对于它们的求和顺序没有影响。你想要做的是,在计算所有平均值后仅对所有条目进行一次排序,因此你需要收集这些值。如果你想按照平均值排序,使用元组以平均值作为第一个字段,这样排序将完全符合你的要求:

# The list that will hold the pairs of
# average score and name
avgs = []

# Your initial loop
for name in user_scores:
    x = user_scores[name]

    # Just collect the pair
    avgs.append((sum(x) / float(len(x)), name)

# Now sort it
avgs = sorted(avgs)

# Print it
for avg, name in avgs:
    print (name, avg)

然而,更加Python风格的做法是使用列表推导式:
# A function for the average
def average(lst):
    return sum(lst) / float(len(lst))

# The averages as list comprehension    
avgs = sorted((average(scores), name)
              for name, scores in user_scores.items())

# Print it
for avg, name in avgs:
    print (name, avg)

假设您正在使用Python 3,如果使用Python 2,请使用iteritems()viewitems()


谢谢,第一个完美地工作了。 - user5637300
你可以使用生成器表达式代替列表推导式。换句话说,sorted((average(scores), name) for name, scores in user_scores.items()) 不需要方括号。 - 200_success
当然,你是对的。我只是为了与收集列表的示例保持连续性而使用了列表推导式。但既然 OP 无论如何都使用了第一个版本,我将编辑源代码以使用生成器。 - Jens Grabarske

1
假设使用Python 3...
在第二个for循环中,如果你在计算平均分时就打印它们,那么你不可能按照期望的顺序打印它们。你需要将其拆分为两个阶段。
计算平均分数:
avg_user_scores = {
    user: sum(map(float, scores))/len(scores)
    for user, scores in user_scores.items()
}

然后按降序打印它们:
for name, score in sorted(avg_user_scores.items(), key=itemgetter(1), reverse=True):    
    print(name, score)

operator.itemgetter(1) 是获取元组的第二个元素(即 lambda t: t[1])即平均分数的一种方式。


整个程序:

from collections import defaultdict, deque
from operator import itemgetter

user_scores = defaultdict(lambda: deque(maxlen=3))
with open('highscores.csv') as file:
    for line in file:
        name, score = line.split(',')
        user_scores[name].append(float(score))
avg_user_scores = {
    user: sum(scores) / len(scores)
    for user, scores in user_scores.items()
}
for name, score in sorted(avg_user_scores.items(), key=itemgetter(1), reverse=True):    
    print(name, score)

0
将每个人的三个分数求平均值。将这些值放入一个字典中(键为人名)。调用sorted()方法。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接