1

These are my inputs

hand = {'*': 1, 'v': 2, 'n': 1, 'i': 1, 'l': 2}
string = 'abc'

I need to replace '*' with each character from string and append the new dict to a list. The output I need is this:

[{'v': 2, 'n': 1, 'i': 1, 'l': 2, 'a': 1}, {'v': 2, 'n': 1, 'i': 1, 'l': 2, 'b': 1}, {'v': 2, 'n': 1, 'i': 1, 'l': 2, 'c': 1}]

This is what I have done and it doesn't work. I have tried a few different approaches but with no success.

del hand['*']
for x in string:
    item = {x: 1}
    newHand = hand
    newHand.update(item)
    print(newHand)
    list.append(newHand)
    newHand.pop(x)
print(list)

The output below is something that I'm trying to avoid:

{'v': 2, 'n': 1, 'i': 1, 'l': 2, 'a': 1, 'b': 1, 'c': 1}

Thanks

SHR
  • 496
  • 2
  • 4
  • 13
  • Possible duplicate of [How to clone or copy a list?](https://stackoverflow.com/questions/2612802/how-to-clone-or-copy-a-list) - it is the same problem for lists - you got a dict , but the principle is the same... – Patrick Artner Mar 07 '19 at 16:13

1 Answers1

1

This creates just a new name to the same data:

newHand = hand

You are always modifying the same dictionary. You store the reference into your list (btw. don't use list as a variable name - you shadow the built-in list()). If you print the id() of your list-contents you'll see they are all the same:

print( id(x) for x in list) # try that to see its the same object trice

You need to copy the data instead to create three distinct dictionaries.

I opted instead to update 1-elem dict from your string and updating them with the remainders of hand after popping '*':

hand = {'*': 1, 'v': 2, 'n': 1, 'i': 1, 'l': 2}

s = hand.pop("*")  # removes * and stores the calue
t = "abc"

# create a list of new dicts wich 1 elem each
l = [ {c:s} for c in t]

# update all inner dicts
for d in l:
    d.update(hand) # add what is in hand left

print(l)

Output:

[{'a': 1, 'i': 1, 'v': 2, 'l': 2, 'n': 1}, 
 {'i': 1, 'b': 1, 'v': 2, 'l': 2, 'n': 1}, 
 {'i': 1, 'c': 1, 'v': 2, 'l': 2, 'n': 1}]

You can find more pieces of information about copy of mutables here: How to clone or copy a list?


To also update existing keys:

for d in l:
    for thing in hand:
        d.setdefault(thing,0)       # create key if not exists and set to 0
        d[thing] += hand[thing]     # add hands value on top
Patrick Artner
  • 50,409
  • 9
  • 43
  • 69
  • Thank you for your help! – SHR Mar 07 '19 at 16:18
  • After reviewing this solution, I came across an issue with that. If there is an element in t that is also present in hand, it will not be updated and this is something that I don't want. For example, if t = aeiou, one element in the list is missing character 'i'. – SHR Mar 07 '19 at 17:36
  • The 3rd element is without the original 'i' from hand: – SHR Mar 07 '19 at 17:41
  • [{'a': 1, 'v': 2, 'n': 1, 'i': 1, 'l': 2}, {'e': 1, 'v': 2, 'n': 1, 'i': 1, 'l': 2}, {'i': 1, 'v': 2, 'n': 1, 'l': 2}, {'o': 1, 'v': 2, 'n': 1, 'i': 1, 'l': 2}, {'u': 1, 'v': 2, 'n': 1, 'i': 1, 'l': 2}] – SHR Mar 07 '19 at 17:41
  • @SHR your first data did not have that problem.I added a manual update of your dicts - you can use that with your new problem. – Patrick Artner Mar 07 '19 at 17:53
  • I appreciate your time. – SHR Mar 07 '19 at 18:03