如何按照元素的值对列表进行排序,并在Python

时间:2017-01-01 03:14:21

标签: python list list-comprehension

让我们说我有一个游戏,其中玩家用唯一的数字表示。然后,说我有一堆随机选择的玩家名单,名为playerList。因此,列表没有被排序(例如,这可能代表一些玩家报名参加一些比赛)。然后,我有一个名为playerLevel的第二个列表,其中第i个条目告诉你第一个玩家所处的等级。

因此,如果playerLevel = ['X','Y','X','Z'],则玩家1和3在等级X上,玩家2在等级Y上,玩家4在等级Z上。

使用列表推导,我如何制作一个新的列表(让我们称之为相同级别),其中玩家编号被分类到子列表中,基于玩家处于同一级别?

所以,在这个例子中,sameLevel = [[1,3],[2],[4]]

我想以一种看起来优雅的方式做到这一点。理想情况下,使用一个主循环,看起来像“在playerLevel中的元素:”等等。我怎样才能做到这一点?谢谢!

4 个答案:

答案 0 :(得分:3)

它本身不使用列表推导,但这样做:

from collections import defaultdict
playerLevel = ['X', 'Y', 'X', 'Z']
sameLevel = defaultdict(list)
for idx, level in enumerate(playerLevel):
    sameLevel[level].append(idx)
print(sameLevel.values())

这会产生[[1], [0, 2], [3]]

答案 1 :(得分:2)

我会使用字典而不是嵌套列表:

In [1]: pLevels = ["X", "Y", "Z", "X"]

In [2]: from collections import defaultdict

In [3]: lvlPlayerMap = defaultdict(list)

In [4]: for (pID, lvl) in enumerate(pLevels): lvlPlayerMap[lvl].append(pID)

In [5]: lvlPlayerMap
Out[5]: defaultdict(list, {'X': [0, 3], 'Y': [1], 'Z': [2]})

答案 2 :(得分:0)

使用itertools.groupby

import operator, itertools
players = random.choices('xyzdeftup', k=20)
level = operator.itemgetter(1)
player = operator.itemgetter(0)
players = sorted(enumerate(players), key = level)
groups = itertools.groupby(players, key = level)
#for level, group in groups:
#    print('{}:\n\t{}'.format(level, str(list(map(player, group)))))
result = [list(map(player, group)) for level, group in groups]

答案 3 :(得分:0)

使用itertools.groupby的替代实现(wwii打败了我)。几个小时前,有人posted a question对这个确切的功能有用了。

<强>代码

import itertools

X = 5
Y = 10
Z = 15

PLAYER_LEVELS = [X, Y, X, Z]

def group_by_player_level(player_levels):
    def by_level(pair):
        return pair[1]

    sorted_levels = sorted(enumerate(player_levels), key=by_level)
    return [[i + 1 for (i, _) in g] for _, g in itertools.groupby(sorted_levels, key=by_level)]

if __name__ == '__main__':
    print(group_by_player_level(PLAYER_LEVELS))

<强>输出

[[1, 3], [2], [4]]