-2

Im trying to create a dictionary with a dictionary comprehension. The dict should look like this:

So far I tried:

player_objects = ['list', 'of', 'player_objects']
extended_data = {player_name:{'Money':100, 'Items'=['Item1', 'Item2']}}
data = {player_object:extended_data.get(player).get('Items') for player in extended_data for player_object in player_objects}
#expected output:
data = {player_object:['list', 'of', 'items']}

But this returns a dict where all players have the Items of the last player, I also figured out this comes from for player_object in player_objects. Can I get the dict I want only with dictionary comprehension?

optimalic
  • 511
  • 3
  • 17
  • 1
    Please try to rewrite your code fragments so that this whole thing is [*minimal*, *verifiable* and *complete*](/help/mcve). Perhaps replace "players" with strings that are their names, showing the input and desired output – Antti Haapala -- Слава Україні Sep 01 '17 at 20:05
  • Just a hunch, but I feel like this code could be made a lot simpler with a Player class... – bphi Sep 01 '17 at 20:08
  • Is there any property mapping a `player_object` to the player's name? – Brett Beatty Sep 01 '17 at 20:09
  • @bphi The player_object actually is a class either [this](http://discordpy.readthedocs.io/en/latest/api.html#discord.User) or [this](http://discordpy.readthedocs.io/en/latest/api.html#discord.Member) Bretty Beatty I think this also covers your question if I understood you right? – optimalic Sep 01 '17 at 20:14
  • Why don't you make money and items attributes of the player class? This way you can manipulate those things using the class methods... – agtoever Sep 01 '17 at 20:23
  • I didn't write the player class myself, they are from a libary(discord.py) as you can see in the links above – optimalic Sep 01 '17 at 20:25
  • Can you subclass the player class to add those attributes? – Josh Karpel Sep 01 '17 at 20:26
  • I'm going to try @JoshKarpel – optimalic Sep 01 '17 at 20:28
  • I think I can't because I get the current player_objects from a function of a class from the libary. I would have to create a sub class of the class who returns me the player_objects and overwrite this functions right?@JoshKarpel – optimalic Sep 01 '17 at 20:38
  • @MushroomMauLa Agreed. Probably not practical or stable. – Josh Karpel Sep 01 '17 at 20:44
  • @MushroomMauLa Can you simply assign the extra attributes you want once you have the `player_object`? This should be possible unless the class was defined using `__slots__`. – Josh Karpel Sep 01 '17 at 20:50
  • Let us [continue this discussion in chat](http://chat.stackoverflow.com/rooms/153501/discussion-between-mushroommaula-and-josh-karpel). – optimalic Sep 01 '17 at 20:54

1 Answers1

1

Although there's probably a more Pythonic solution, I do have a fix for your original code. The problem is the double for in your dict comprehension. When you do that you iterate over both player_objects and extended_data independently. Instead, iterate over one of them and use those names to access the other dict. You also can't use self in that comprehension - it doesn't refer to anything, unless your code happens to be living in a class method.

Here's a mockup:

player_objects = ['player_a', 'player_b', 'player_c']
extended_data = {
    'player_a': {'Money': 100, 'Items': ['dagger', 'armor']},
    'player_b': {'Money': 50, 'Items': ['sword', 'shield']},
    'player_c': {'Money': 20, 'Items': ['boots', 'staff']},
}

items_by_player = {player: extended_data[player].get('Items') for player in player_objects}

print(items_by_player)
# {'player_a': ['dagger', 'armor'], 'player_b': ['sword', 'shield'], 'player_c': ['boots', 'staff']}
Josh Karpel
  • 2,110
  • 2
  • 10
  • 21