Reputation: 123
What is efficient way of removing empty values from dictionary which is saved inside the list.
list1 = [{'l1k1': 'l1v1', 'l1k2': 'l1v2'}, {'l2k1': 'l2v1', 'l2k2': ''}]
list2 = []
for l in list1:
d = {}
for k, v in l.items():
if v.strip() is not None or v.strip() != '':
d[k] = v
list2.append(d)
print(list2)
Actual Output:
[{'l1k1': 'l1v1', 'l1k2': 'l1v2'}, {'l2k1': 'l2v1', 'l2k2': ''}]
Expected Output:
[{'l1k1': 'l1v1', 'l1k2': 'l1v2'}, {'l2k1': 'l2v1'}]
Upvotes: 3
Views: 8609
Reputation: 1
list1 = [{'l1k1': 'l1v1', 'l1k2': 'l1v2'}, {'l2k1': 'l2v1', 'l2k2': ''}]
The most efficient way is this:
list2 = [{k: v for k,v in dic.items() if v} for dic in list1]
PS:
using .strip()
works for strings only and since you have all types of False
/None
/""
values those would not be removed, infact you would get bugs. Also: using .strip()
just to remove " "
(with a space) is wrong since " "
is not even a False
value in Python and you really should not consider it as such also. To remove certain characters (other than empty ones as in your question) you should try to create and use a different specific function instead that does just that.
Upvotes: 0
Reputation: 6935
Try this :
list2 = [{k:v for k,v in i.items() if v!= '' or v.strip() != ''} for i in list1]
We can use dict-comprehension as well as list-comprehension simultaneously. We loop for every element (which is a dictionary) of list1
, and just take those key-value pairs where the value or value.strip()
for the corresponding key in the dictionary is not a vacant string.
A shorter version for cancelling the values with None
type also:
list2 = [{k:v for k,v in i.items() if v} for i in list1]
Upvotes: 9
Reputation: 236122
Try this:
list1 = [{'l1k1': 'l1v1', 'l1k2': 'l1v2'}, {'l2k1': 'l2v1', 'l2k2': ''}]
list2 = [{ k: v for k, v in d.items() if v and v.strip() } for d in list1]
Notice that the correct check to do here is v and v.strip()
, that ensures that the string is not None
and is not all spaces. It works as expected:
list2
=> [{'l1k1': 'l1v1', 'l1k2': 'l1v2'}, {'l2k1': 'l2v1'}]
It's efficient because it uses list comprehensions and dictionary comprehensions, which are faster than doing explicit loops. Also, it's quite compact and idiomatic :)
Upvotes: 7
Reputation: 4279
making a copy of your list is not very efficient, unless you WANT to keep the original as well. you can just remove the entries that are "empty" like so:
list1 = [{'l1k1': 'l1v1', 'l1k2': 'l1v2'}, {'l2k1': 'l2v1', 'l2k2': ''}]
for item in list1:
for key in list(item.keys()):
if not item[key].strip():
del item[key]
this part list(item.keys())
is important. why list? because python doesnt like it when you change the size the dict during iteration, if we pre-get the keys, we will be iterating on a list instead of a generator.
not item[key].strip()
is also a good to note, empty strings evaluate to False
while non-empty string evaluate to True
*note: strictly speaking the .keys()
isnt necessary, but it does help readability if youre new to python
Upvotes: 0
Reputation: 546
Here is a simple alternative, not using list comprehension that may be easier for you to follow:
for d in list1:
for k in d.keys():
if d[k] != '':
list2.append({k:d[k]})
Upvotes: 0