从两个不同的数组中排序值

时间:2017-10-16 14:44:34

标签: python sorting

我找到了所有的价值观和一切,我尝试了排序,但它分开排序而不是一起排序。我想按年份排序,成绩应该遵循多年的价值观。但是,当我按年份排序时,它只会排序数年,而是保持成绩不变。

打开文件时, 它会给我一些类似的东西:

Year,Grade
2000,84
2001,34
2002,82
2012,74
2008,90

等等。所以我计算了平均值和一切。

years, average_grades = [],[]
avg = []
d = {}

with open(file,'r') as f:
    next(f)
    for line in f:
        year, grade = (s.strip() for s in line.split(','))
        if year in d:
            d[year][0] += int(grade)
            d[year][1] += 1
        else:
            d[year] = [int(grade),1]

    for year, grades in d.items():
        years.append(str(year))
        average_grades.append(float(grades[0]) / grades[1])

    return years, average_grades

没有排序,它会给我类似的东西:

2001 74.625
2006 72.241
2012 70.875
2017 69.1981
2005 72.5
2008 71.244
2014 73.318
2004 72.1
2007 72.88
2000 73.1

With years.sort(), it would give me similar to this:
2000 74.625
2001 72.241
2002 70.875
2003 69.1981
2004 72.5
2005 71.244
2006 73.318
2007 72.1

所以排序只能使用多年,但不会对成绩这样做。 这个问题一直困扰着我很长一段时间。我不打算用熊猫。

4 个答案:

答案 0 :(得分:1)

使用zip将其加入tuple,然后加入sort

示例

>>> y = [3, 2, 4, 1, 2]
>>> g = [0.1, 0.4, 0.2, 0.7, 0.1]

>>> mix = list(zip(y,g))
>>> mix
=> [(3, 0.1), (2, 0.4), (4, 0.2), (1, 0.7), (2, 0.1)]

>>> sorted(mix)
=> [(1, 0.7), (2, 0.1), (2, 0.4), (3, 0.1), (4, 0.2)]

订单中的#print:

>>> for ele in sorted(mix): 
        print(ele[0],ele[1]) 

1 0.7
2 0.1
2 0.4
3 0.1
4 0.2

注意对于2年,0.10.4有两个值,它会处理它,更优先考虑{{1} }和下一个year

答案 1 :(得分:0)

您想在return语句之前添加此行:

years, average_grades = zip(*sorted(zip(years, average_grades), key=lambda p: p[0]))

这是做什么的?

内部zip(years, average_grades)告诉python将iterables yearsaverage_grades的每个元素组合成一个元组数组。

sorted(..., key=lambda p: p[0])sorted实用程序,除非它正在对该对进行操作,否则它需要知道如何对该对进行排序。所以我们传递一个lambda函数,说“看第一部分。”

外部zip(*...)获取从排序返回的结果,它是元组列表,并将其转换回两个列表。 *告诉它将列表视为一堆参数,所以你要成对传递给zip。 zip接受任意数量的元组参数,并将它们拆分为组件部分。在这种情况下,它采取十对并将其分成2个长度为10的元组。

只要您的iterables长度相同,这就是将它们排序在一起的“基本”机制。

答案 2 :(得分:0)

我希望这个例子有用,所以:

years = [2001,2000,2002]
average_grades = [5,10,15]
result = zip(years,average_grades)
for item in sorted(result, key=lambda x: x[0]):
    print('{} {}'.format(*item))
#2000 10
#2001 5
#2002 15

答案 3 :(得分:0)

替代解决方案正在取得结果并将它们压缩在一起。由于您似乎可以控制文件的读取,我建议永远不要将年份和成绩分开

在我看来,这比后来将两个列表与zip结合起来更容易。

years, average_grades = [],[]
avg = []
d = {}

with open(file,'r') as f:
    next(f)
    for line in f:
        year, grade = (s.strip() for s in line.split(','))
        if year in d:
            d[year][0] += int(grade)
            d[year][1] += 1
        else:
            d[year] = [int(grade),1]

# Iterator-Expression to convert 'd' dictionary into list of tuples.
# Puts (year, average grade) into a new list.
year_grade = [(year, float(grade_tuple[0]) / grade_tuple[1]) \
               for year, grade_tuple in d.items()]

# Sorting is optional, if you return the list of tuples.
# Use 'key=lambda ...' to sort over the year (the first element of the tuple).
# Technically, specyfing the 'key' is not necessary as the default would be
# to sort over the first element first.
year_grade.sort(key=lambda x: x[0])

return year_grade
# Alternatively, return the list of tuples as a list of two tuples: years, grades
return zip(*year_grade)

其他改进

您可以使用defaultdict来避免if year in d阻止:

from collections import defaultdict

d = defaultdict(lambda: [0, 0])

with open(fname,'r') as f:
    next(f)
    for line in f:
        year, grade = (s.strip() for s in line.split(','))
        d[year][0] += int(grade)
        d[year][1] += 1

    def avg(t):
        return float(t[0]) / t[1]
    year_grade = [(y, avg(g)) for y, g in d.items()]
    year_grade.sort()

    return zip(*year_grade)  # Python3: tuple(zip(*year_grade))