0

I have a dictionary like

dict1 = {1 : {'objects_1' : [1289,12678]} , 6 : {'objects_2' : [7798,808]} , 8 : ['object_2' : [76789,879]} }

Basically, the dict1.keys() are 1,6,8,10,15,...100 Is there a way to reassign these values with consecutive integers starting from 1,2,3,4,5..100

bicarlsen
  • 1,241
  • 10
  • 27
Raghavi R
  • 65
  • 5

5 Answers5

1

I would suggest recreating the dictionary using a dictionary comprehension along with enumerate.

new_dict = { index: val for index, ( _, val ) in enumerate( old_dict.items() ) }
bicarlsen
  • 1,241
  • 10
  • 27
1

So what you need to do is to go over the dictionary items. You can do that by iterating on keys with keys() method.

Then you could create an enumerator for each iteration. You can do that with enumerate(). enumerate() has its own value sequential starting from 0 if you do not declare anything or from a start parameter.

So for each iteration now you have the enumerate value and your key. You can assign a new key to your dictionary with the enum value as key, and as assigned value the result of the pop() method for the specific key you are each time.

Code example:

dict1 = {1 : {'objects_1' : [1289,12678]} , 6 : {'objects_2' : [7798,808]} , 8 : {'object_2' : [76789,879]} }

print(dict1)

for enum, i in enumerate(dict1.keys(), 1):
    print (enum, i)

    dict1[enum] = dict1.pop(i)

print(dict1)

EDIT based on Mad Physicist comment and thanks for reminding me

kakou
  • 636
  • 2
  • 7
  • 15
  • Enumerate takes a start argument – Mad Physicist Jun 15 '21 at 11:42
  • What if: `dict1 = {8 : {'objects_1' : [1289,12678]} , 6 : {'objects_2' : [7798,808]} , 1 : {'object_2' : [76789,879]} }`? – Booboo Jun 15 '21 at 11:47
  • I do not think this is what he asks. It seems that it is just needed to assign keys in sequence. – kakou Jun 15 '21 at 11:54
  • The point I am making is that your algorithm requires that the dictionary you are processing already starts off with the keys in ascending sequence 1, 6, 8. It will fail when you iterate the input keys you get instead 8, 6, 1. That is, you are returned a key value (i.e. 1) for which you have *already* assigned a key value. Why don't you just *try* replacing `dict1` with the above declaration and see what I am talking about. – Booboo Jun 15 '21 at 12:26
  • 1
    I guess you could just sort the keys in such cases. Still not in the question description tho. – kakou Jun 15 '21 at 12:37
  • @KarolosK. Correct! I already sorted it so no issues there, THANKS! – Raghavi R Jun 15 '21 at 13:21
  • Being sorted doesn't necessarily help. What if the input keys were 0, 1, 2? That is sorted and it would still fail. – Booboo Jun 15 '21 at 13:50
  • you could create a new dict and get the values there instead of replacing keys in the original dict. – kakou Jun 15 '21 at 14:01
1

Create a New Dictionary and copy dict1.values() to it.

new_dict = {}

for key,value in enumerate(dict1.values(),1):
    new_dict[key] = value

# Output:
# new_dict = {1: {'objects_1': [1289, 12678]}, 2: {'objects_2': [7798, 808]}, 3: {'object_2': [76789, 879]}}
Ram
  • 4,724
  • 2
  • 14
  • 22
1

There is no need to use any explicit for-loops to achieve this. We can simply leverage zip and that it stops itself when one of two iterables is exhausted. We can create some arbitrarily large range as well since it is not all stored in memory either.

dict(zip(range(1, 1_000), dict1.values()))

{1: {'objects_1': [1289, 12678]},
 2: {'objects_2': [7798, 808]},
 3: {'object_2': [76789, 879]}}

Disclaimer: This will work as expected in Python 3.7+ as dict's now preserve items in order of insertion. Otherwise we would have to use OrderedDict.

gold_cy
  • 13,648
  • 3
  • 23
  • 45
1

I wouldn't make any assumptions as to the insertion order of the keys, assuming you want to update the dictionary in place.

dict1 = {8 : {'objects_1' : [1289,12678]} , 6 : {'objects_2' : [7798,808]} , 1 : {'object_2' : [76789,879]} }
old_keys = list(dict1.keys())
for idx in range(1, len(old_keys) + 1):
    if idx in old_keys:
        old_keys.remove(idx)
    else:
        old_key = old_keys.pop(0)
        dict1[idx] = dict1.pop(old_key)
print(dict1)

Prints:

{1: {'object_2': [76789, 879]}, 2: {'objects_1': [1289, 12678]}, 3: {'objects_2': [7798, 808]}}

Granted this could change the insertion order of the values but will handle any arbitrary input.

If you are running Python 3.7 (or CPython 3.6) or later where the assumption is that a set maintains insertion order and its pop method will remove items in insertion order, then you could use:

dict1 = {0 : {'objects_1' : [1289,12678]} , 1 : {'objects_2' : [7798,808]} , 2 : {'object_2' : [76789,879]} }
old_keys = set(dict1.keys())
for idx in range(1, len(old_keys) + 1):
    if idx in old_keys:
        old_keys.remove(idx)
    else:
        old_key = old_keys.pop()
        dict1[idx] = dict1.pop(old_key)
print(dict1)
Booboo
  • 38,656
  • 3
  • 37
  • 60