1

is there a way to add string to all my keys in dictionary without creating a new dictionary? I tried several ways but I get the following error:

    for key in result:
RuntimeError: dictionary keys changed during iteration

My code:

def get_temps_servers():
    result = dict(re.findall(r"^(.*?) {2,}.*?(\d+C|\d+Watts)", text, flags=re.M))
    name = "Test"
    for key in result:
        x = f"{name} {key}"
        result[x] = result[key]
        del result[key]
    print(result)
    return result

This is how my orginal dictionary look:

result = {'CPU1 Temp': '35C', 'CPU2 Temp': '39C', 'System Board Inlet Temp': '18C', 'System Board Exhaust Temp': '29C', 'System Board Pwr Consumption': '130Watts'}

It works great if I create a new dictionary that is copied from the original dictionary, like this one:

def get_temps_servers():
    result = dict(re.findall(r"^(.*?) {2,}.*?(\d+C|\d+Watts)", text, flags=re.M))
    name = "Test"
    res = {f"{name} {key}": val for key, val in result.items()}
    print(res)
    return res

And this is the result:

res = {'Test CPU1 Temp': '35C', 'Test CPU2 Temp': '39C', 'Test System Board Inlet Temp': '18C', 'Test System Board Exhaust Temp': '29C', 'Test System Board Pwr Consumption': '130Watts'}

Is there a way to get the desired result without creating a new dictionary?

1
  • 3
    Why build the first dict at all? return {f'{name} {key}': val for key, val in re.findall(...)}. Commented Apr 8, 2021 at 13:50

2 Answers 2

5

It's posible, but a mess. The answer given by Mad Physicist works - but there are edge cases and you need to make a list copy of the dictionary keys to make it work.

It's much easier to use a dictionary comprehension instead, which is just one line.

name = 'Test'
result = {f"{name} {key}" : value for key, value in  result.items()}
Sign up to request clarification or add additional context in comments.

6 Comments

What edge cases?
Also keep in mind that copying a list of keys is cheaper than the whole hashtable.
The edge case is that if the name is "test" and the dictionary already has a key "1" and a key "test 1" - then this would kill the second entry... So you need to ensure this doesn't happen.
Good catch. Sorting backwards by length will fix that. Will add momentarily.
FWIW, I would generally use the comprehension myself.
|
4

You have to swap out keys in the dictionary object, since there is no such thing as "changing" an immutable key. One way to do that is to make an independent list:

for key in list(result):
    x = f"{name} {key}"
    result[x] = result[key]
    del result[key]

Wrapping result in list ensures that you are iterating over a separate object while modifying result. This leaves open the corner case where your original has keys like 'x' and 'Test x'. Depending on order of iteration, you may end up overwriting a key before it gets copied. To avoid this situation, you can sort the keys backwards by length before processing:

for key in sorted(result, key=len, reverse=True):
    ...

2 Comments

The example causes an error for me: TypeError: 'reversed' is an invalid keyword argument for sort() - this should be reverse instead.
@576i. Thanks for the catch. Fixed that too

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.