Palla veera
Palla veera

Reputation: 123

What is efficient way of removing empty values from dict inside list?

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

Answers (5)

Ardian Maliqaj
Ardian Maliqaj

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

Arkistarvh Kltzuonstev
Arkistarvh Kltzuonstev

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

Óscar López
Óscar López

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

Nullman
Nullman

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

Rustang
Rustang

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

Related Questions