for k, v in mydict.iteritems():
if v is None:
mydict[k] = ''
In a more general case, e.g. if you were adding or removing keys, it might not be safe to change the structure of the container you're looping on -- so using items to loop on an independent list copy thereof might be prudent -- but assigning a different value at a given existing index does not incur any problem, so, in Python 2.any, it's better to use iteritems.
In Python3 however the code gives AttributeError: 'dict' object has no attribute 'iteritems' error. Use items() instead of iteritems() here.
Refer to this post.
Answer from Alex Martelli on Stack Overflowfor k, v in mydict.iteritems():
if v is None:
mydict[k] = ''
In a more general case, e.g. if you were adding or removing keys, it might not be safe to change the structure of the container you're looping on -- so using items to loop on an independent list copy thereof might be prudent -- but assigning a different value at a given existing index does not incur any problem, so, in Python 2.any, it's better to use iteritems.
In Python3 however the code gives AttributeError: 'dict' object has no attribute 'iteritems' error. Use items() instead of iteritems() here.
Refer to this post.
You could create a dict comprehension of just the elements whose values are None, and then update back into the original:
tmp = dict((k,"") for k,v in mydict.iteritems() if v is None)
mydict.update(tmp)
Update - did some performance tests
Well, after trying dicts of from 100 to 10,000 items, with varying percentage of None values, the performance of Alex's solution is across-the-board about twice as fast as this solution.
Updating python dictionary in a loop - Code Review Stack Exchange
python - How to update the values in a nested dictionary with a for loop? - Stack Overflow
python - Update dictionary with a for loop so that the same key is inserted multiple times - Stack Overflow
Python - Updating dictionary in a for loop - Stack Overflow
Your suspicions are correct, this is called using comprehension syntax for side-effects, and is normally bad practice.
A better way to do this is with a for loop
for item in x:
# this also gets rid of your random number list
item['key3'] = random.random()
Instead of iterating over range(len(x)) and ignoring the value, you can simply iterate over x and ignore the value:
x_randoms = [random.random() for _ in x]
Instead of enumerating x only to access x_randoms, you can use zip to iterate over both in parallel:
for xdic, xr in zip(x, x_randoms):
xdic['key3'] = xr
You can do it like so, also do not use dict to name the dictionary, its already a reserved name.
In [9]: sample
Out[9]: {'first': 3, 'second': 3}
In [10]: sample = {"first":{"firstInner":1}, "second":{"secondInner":2}}
In [11]: for key,value in sample.items():
...: for k in value.keys():
...: value[k] = 3
...:
In [12]: sample
Out[12]: {'first': {'firstInner': 3}, 'second': {'secondInner': 3}}
Avoid using dict as variable names as it is reserved.
Iterate over the outer dict items and then for every value of outer dict update the values.
dicts = {"first":{"firstInner":1}, "second":{"secondInner":2}}
for key, val in dicts.items():
for i in val:
val[i] = 3
print(dicts)
Output:
{'first': {'firstInner': 3}, 'second': {'secondInner': 3}}
The whole idea of dictionaries is that they have unique keys.
What you can do is have 'result' as the key and a list as the value, then keep appending to the list.
>>> d = {}
>>> for i in range(0,5):
... d.setdefault('result', [])
... d['result'].append(i)
>>> d
{'result': [0, 1, 2, 3, 4]}
Keys have to be unique in a dictionnary, so what you are trying to achieve is not possible. When you assign another item with the same key, you simply override the previous entry, hence the result you see.
Maybe this would be useful to you?
>>> d = {}
>>> for i in range(3):
... d['result_' + str(i)] = i
>>> d
{'result_0': 0, 'result_1': 1, 'result_2': 2}
You can modify this to fit your needs.
The two inner loops seem wrong, you want to traverse the periods and the grades simultaneously, not traversing all the periods for each grade (that's the effect caused by nesting a loop inside another.)
Assuming that there's an equal number of grades and periods the correct way to build a dictionary would be:
final = dict(zip((x.get_text() for x in periods), grades))
The "long" way to do this (as requested in the comments) would be:
final = {}
for period, grade in zip(periods, grades):
final[period.get_text()] = grade
Also notice that at the end you'll only get a dictionary with the periods/grades of the last class, because you're iterating and creating a new dictionary for each class and discarding the previous dictionaries.
I have found a way to add each period and grade to the dictionary.
final={}
for classes in soup.find_all("div", "AssignmentClass"):
grades = classes.findAll("span")[5]
periods = classes.findAll("a", "asmt_link")
for p, g in zip(periods, grades):
final.setdefault(p.get_text(), g)
Result:
{'Period 1': 97.00000, 'Period 2': 84.93440, 'Period 3': 25.83333, 'Period 4': 86.38029, 'Period 5': 86.15000, 'Period 6': 86.87500, 'Period 7': 66.76380}
Using .setdefault() solved my problem.
Iterating-and-updating a mapping is pretty gnarly and Python certainly has no support specifically for that, especially when you want to update not just the values but the keys as well: that translates to changing the internal layout of the dictionary on the fly, which affects the order of iteration for instance (you'd pop() each key and reinsert whatever replacement made sense, but then depending on the mapping you might have the issue of trying to replace keys you had not popped yet resulting in inconsistent behaviour).
Technically possible but generally a very bad idea.
The better approach is usually to just create a new dict from the old one e.g.
transformed = dict(
(
"type" if key == "sub_type" else key,
"add" if value == "additive" else value
)
for key, value in original.items()
)
Although for the specific case where you want to replace one (key, value) pair if it's present, you can just pop() the offending key then reinsert the replacement e.g.
if val := original.pop("sub_type", None):
# convert additive to add, leave other types as-is
if val = "additive":
val = "add"
original["type"] = val
You can simply do this:
rename key:
In [1626]: d = {'sub_type': 'additive', 'data_type': 'Number', 'value': False, 'field_type': 'measure'}
In [1628]: d['type'] = d.pop('sub_type')
rename value:
In [1630]: for k,v in d.items():
...: if v == 'additive':
...: d[k] = 'add'
...:
Output:
In [1631]: d
Out[1631]: {'data_type': 'Number', 'value': False, 'field_type': 'measure', 'type': 'add'}
I'm currently studying the book Python Crash Course. Chapter 6 is about dictionaries, and I wrote this code:
# Create an empty list for aliens.
aliens = []
# Make 30 green aliens.
for alien_number in range(30):
new_alien = {"color": "green"}
aliens.append(new_alien)
# Change the first three aliens into yellow aliens.
for alien in aliens[:3]:
alien = {"color": "yellow"}
print("The first five items of the aliens list:")
for alien in aliens[:5]:
print(alien)It doesn't work as intended. The first three list items should have the color "yellow" instead of "green". Now, here is the correct code from the book:
# Change the first three aliens into yellow aliens.
for alien in aliens[:3]:
alien["color"] = "yellow"
print("The first five items of the aliens list:")
for alien in aliens[:5]:
print(alien)Can you help me understand what the difference is?
You can use an iterator to iterate through the values of binary_list instead:
iter_binary_list = iter(binary_list)
for truck in Trucks:
for day in Days:
requests[truck][day] = next(iter_binary_list)
You can use dictionary comprehension to do it in a one liner and more "pythonic" way as the following:
it = iter(binary_list)
status = {x: {d: next(it) for d in Days} for x in Trucks}
# outputs: {'A': {'Monday': 1, 'Tuesday': 1, 'Wednesday': 1, 'Thursday': 1, 'Friday': 1, 'Saturday': 1, 'Sunday': 1}, 'B': {'Monday': 1, 'Tuesday': 1, 'Wednesday': 1, 'Thursday': 1, 'Friday': 1, 'Saturday': 1, 'Sunday': 1}}