-1

So, I am making an inventory system for my game but like always, there is an error. This is my fault of course, but I can't figure a way around it. I need the code to add an item into the dict without replacing the current key. For example, a player catches a fish:

inventory = {} #This is the dict to hold all the items

for x in range(1,10):
    inventory['slot{0}'.format(x)] = {'type':'Fish'}
    break

But if you catch say two fish, it will always take up the first slot

###Output: 
{'slot1':{'type':'Fish'}}

So then I tried making an if a statement about if a slot was full try the next one

for x in range(1,10):
    if inventory['slot{0}'.format(x)] != {}:
        x += 1
    inventory['slot{0}'.format(x)] = {'type':'Fish'}
    break

Here is the expected output for two fish caught:

###Output

{'slot1':{'type':'fish'},'slot2':{'type':'fish}}

But then I get the Key error that the nested dictionary doesn't exist. So, I need some help.

Duncster
  • 13
  • 6
  • Do you mind giving an example of expected output? – cischa Dec 06 '19 at 21:29
  • 3
    Is there any reason you aren't just using a list? You could just append your items. – Mark Dec 06 '19 at 21:39
  • Does this answer your question? [Check if a given key already exists in a dictionary](https://stackoverflow.com/questions/1602934/check-if-a-given-key-already-exists-in-a-dictionary) – Mihai Chelaru Dec 06 '19 at 21:39
  • The `break` in your for loop does not make sense, remove it – Tammo Heeren Dec 06 '19 at 21:39
  • Mark I need a dictionary to map items – Duncster Dec 06 '19 at 21:41
  • If I don't have break it adds ten keys that are the same – Duncster Dec 06 '19 at 21:43
  • You don't need a dictionary for this. A list will give you all the information you need and is much easier to deal with. If `inventory` is a list, then `slot1` is `inventory[0]`. And Tammo is right, the `break` in your for loop makes no sense. It will break on the very first iteration so the for loop is useless. – SyntaxVoid Dec 06 '19 at 22:13

3 Answers3

1

As mentioned in the comments, this is really a job for a list. Including dictionary version for completeness.

With list:

def get_slot_x(inventory, x):
    return inventory[x]

def add_item(inventory, item):
    for i, v in enumerate(inventory):
        if v is None:
            inventory[i] = v
            break
    else:
        raise RuntimeError('nowhere to put item')

def empty_slot_x(inventory, x):
    inventory[x] = None

inventory = [None] * 10

With dict:

slotname = lambda x: 'slot%d' % x

POSSIBLE_SLOTS = list(map(slotname, range(10)))

and if value is None means empty:

def add_item(inventory, item):
    for k, v in inventory.items():
        if v is None:
            inventory[k] = v
            break
    else:
        raise RuntimeError('nowhere to put item')

def get_slot_x(inventory, x):
    return inventory[slotname(x)]

def empty_slot_x(inventory, x):
    inventory[slotname(x)] = None

inventory = collections.OrderedDict.fromkeys(POSSIBLE_SLOTS)

or if you want no-key-present to mean empty:

def add_item(inventory, item):
    for k in POSSIBLE_SLOTS:
        if k not in inventory:
            inventory[k] = v
            break
    else:
        raise RuntimeError('nowhere to put item')

def get_slot_x(inventory, x):
    return inventory.get(slotname(x))

def empty_slot_x(inventory, x):
    inventory.pop(slotname(x), None)

inventory = {}

For any of the above:

add_item(inventory, 'foobar')
assert get_slot_x(inventory, 0) is None
assert get_slot_x(inventory, 0) == 'foobar'
empty_slot_x(inventory, 0)  # You may want to throw errors if nothing is there
assert get_slot_x(inventory, 0) is None

You could also drop slotname entirely and just use integers for your keys, if there is no pressing reason.

Cireo
  • 4,197
  • 1
  • 19
  • 24
0

you can enter your new data to new dict temp = {} and then merge it with your main dict inventory = {**inventory, **temp}

daniel
  • 61
  • 1
  • 7
-2

Here is the code for expected output. Actually you are trying to access the dict key before assigning it.

inventory = {} #This is the dict to hold all the items

for x in range(1,10):
    if 'slot{0}'.format(x) in inventory:
        x += 1
    inventory['slot{0}'.format(x)] = {'type':'Health'}
    break
print(inventory)
Sohaib
  • 566
  • 6
  • 15
  • This somewhat works, the problem is that if the player's inventory is empty, then it throws the error that there is not such thing as slot1 – Duncster Dec 06 '19 at 21:53
  • it will throw error because your dict is empty. so you should try this condition, if 'slot{0}'.format(x) in inventory:x += 1 – Sohaib Dec 06 '19 at 21:59
  • 1
    This will fail if the first and second slots are taken. – Cireo Dec 06 '19 at 22:23
  • This will only work for the first slot. Imagine `slot1` and `slot2` are taken, then you will enter the body of the `if` statement and `x` will become 2. You then exit the `if` statement and let `inventory['slot2'] = {…}` so you've just overwritten whatever was in slot 2. The `x += 1` should be `continue` instead, which will jump back to the top of the loop and do the next iteration. This repeats until you find an empty slot. – SyntaxVoid Dec 06 '19 at 22:23