Reputation: 235
Lets say I have a game where the players are denoted by a unique number. Then, say I have a list with a bunch of randomly chosen players, called playerList. So, the list isn't ordered(this could represent a bunch of players signing up for some contest, for example). Then, I have a second list called playerLevel, where the i'th entry tells you the level the i'th player is on.
So, if playerLevel = ['X', 'Y', 'X', 'Z'], then players 1 and 3 are on level X, player 2 is on level Y, and player 4 is on level Z.
Using list comprehensions, how can I make a new list(lets call it samelevel) where the player numbers are sorted into sublists, based on the players being on the same level?
So, in this example, sameLevel = [[1,3],[2],[4]]
I'd like to do this in a way that looks elegant. Ideally, using a main loop that looks like "for element in playerLevel:" and so on. How can I do this? Thanks!
Upvotes: 3
Views: 88
Reputation: 9076
Alternative implementation using itertools.groupby
(wwii beat me to it). Funnily enough someone posted a question about this exact function just a few hours ago.
Code
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))
Output
[[1, 3], [2], [4]]
Upvotes: 0
Reputation: 1663
It doesn't use a list-comprehension, per se, but this will do it:
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())
This results in [[1], [0, 2], [3]]
.
Upvotes: 3
Reputation: 23753
Using 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]
Upvotes: 0
Reputation: 5572
I would use a dictionary instead of nested lists:
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]})
Upvotes: 2