0

I currently have a dictionary with a numerical index as keys. I know how much values I should have in total in the dictionary and would like to add the missing keys and a null value with those keys in the dictionary. To illustrate I included this example:

dictionary = {'0' : '101',
              '1' : '102',
              '2' : '100',
              '4' : '100.5',
              '6' : '103'}

I know that I have 8 values in my dictionary and so I would like to write a function that turns the above dictionary into:

dictionary = {'0' : '101',
              '1' : '102',
              '2' : '100',
              '3' : None,
              '4' : '100.5',
              '5' : None,
              '6' : '103',
              '7' : None}

Anyone that knows how to achieve this? Thanks in advance.

Kelly Bundy
  • 23,480
  • 7
  • 29
  • 65
SDR3078
  • 45
  • 8
  • 1
    How do you decide what's missing; in your example you found that '5' and '7' were missing, but what about '8', etc. You've got to refine your question to specify that the keys are always single (?) character strings that represent positive integers, and you want to find in all the gaps between those integers. – Mark Lavin Aug 23 '21 at 15:10
  • @MarkLavin, I know that the amount of values should be 8 and as it is a numerical index, the index numbers should go from 0 to 7, which is how I determine which values are missing. – SDR3078 Aug 23 '21 at 15:14
  • You say you have a numerical keys, but your shown keys are all *strings*. Which is it really? – Kelly Bundy Aug 23 '21 at 15:47
  • The API returned the numerical index in string format, I wrote a function to undo it. You can therefore say it was both ;) – SDR3078 Aug 24 '21 at 17:10

7 Answers7

2

Assuming N is the number of items

{**dictionary, **{k: None for k in range(N + 1) if str(k) not in dictionary.keys()}}

However, it might be better to have integers as keys in dictionary, in this way you do not have to cast to str

Edit Thanks to schwobaseggl comment a better version is

{**{str(k): None for k in range(N + 1)}, **dictionary}

see this question about dict merge in python

Andrea Di Iura
  • 467
  • 5
  • 11
1

The following would do the trick:

m = max(map(int, dictionary))
for i in map(str, range(m)):
    if i not in dictionary: 
        dictionary[i] = None

But whether that is necessary is questionable as you could easily provide the default upon lookup: dictionary.get(key) will return None anyway for missing keys.

user2390182
  • 72,016
  • 6
  • 67
  • 89
0

Something like this should do the trick:

dictionary = {'0' : '101', '1' : '102', '2' : '100', '4' : '100.5', '6' : '103'}
key_list = ['0','1','2','3','4','5','6','7']
for k in key_list:
    try:
        dictionary[k]
    except KeyError:
        dictionary[k] = None
0

Otherwise, if you know that your values are following each other, you can use the following function:

def complete_dict(my_dict, begin_at=0, stops_at=8):
    for key in range(begin_at, stops_at):
        if str(key) not in my_dict.keys():
            my_dict[str(key)] = None
    return my_dict

It goes then from begin_at to stops_at - 1.

0

So, since you know that it starts with 0 and goes to some value, you can use range to loop through all the items. If it already exists, just use the same value, and if it doesn't, add None.

d = {'0' : '101', '1' : '102', '2' : '100', '4' : '100.5', '6' : '103'}

for i in range(0, 7):
    d[str(i)] = d.get(str(i), None) 

d = dict(sorted(d.items()))
print(d)

Alternatively, instead of using same dictionary and doing sort by key, you could create new dictionary, which will automatically be sorted, since you're adding them in order.

This is if you're using keys as strings (like in your example). If they are int, just lose the str(i) and use just i

Caldazar
  • 2,801
  • 13
  • 21
0

Can't you just use if k not in dictionary: dictionary[k] = None? Or to be fancy dictionary[k] = dictionary.get(k)

You can fill the Nones if they are not present in the dictionary:

dictionary = {'0' : '101', '1' : '102', '2' : '100', '4' : '100.5', '6' : '103'}
keys = ['0','1','2','3','4','5','6','7']
for k in keys:
    if k not in dictionary:
        dictionary[k] = None

Or if you want to be fancy:

dictionary = {'0' : '101', '1' : '102', '2' : '100', '4' : '100.5', '6' : '103'}
keys = ['0','1','2','3','4','5','6','7']
for k in keys:
    dictionary[k] = dictionary.get(k)

dictionary.get(k) will return the value by key k or None if the value isn't in the dictinary.

Yevhen Kuzmovych
  • 10,940
  • 7
  • 28
  • 48
0

The above examples work fine for filling Nones, but you should consider, maybe in the place where you're retrieving values from the dict, using dictionary.get(key, None) instead of dictionary[key]. This way you'll get None for nonexistent keys, and have your original dictionary.

SurDin
  • 3,281
  • 4
  • 26
  • 28