Reputation: 1824
I have a series of lists (within a dictionary) and I would like to remove any which only have None
as elements. However, the lists have various different formattings e.g.
x=[None,[None],[None]]
x=[None,None,None]
x=[None,[None,None],[None,None]]
where any None
could be replaced with a value.
Any example would be the following dictionary:
dict={"x1": [None,None,None],"x2": [None,[None],[None]], "x3": [None,[1],[0.5]],
"x4":[None,[None,None],[None,None]],"x5":[None,[180,-360],[90,-180]]}
In this case I would like to keep (key,value)
pairs "x3"
and "x5"
as they contain values that are not all None
, but would like to remove "x1"
, "x2"
, and "x4"
thus returning:
dict={"x3": [None,[1],[0.5]], "x5":[None,[180,-360],[90,-180]]}
A simple list comprehension on the various lists (x
) in the dictionary such as
any(e is not None for e in x)
reads [None]
entries as not None
and returns True
.
How can I determine which lists actually contain a value rather than [None]
elements. I have looked at options for removing the square brackets, e.g. using itertools
such as suggested here [Remove brackets from list in Python ], but these all rely on all the elements in the list being formatted in the same way, whereas I have mixed formatting. I am unable to change the formatting as it is required in this format elsewhere in the software.
Upvotes: 0
Views: 138
Reputation: 13090
This solution is similar in nature to that of Keyur Potdar, but it works for all kinds of containers, not only list
:
my_dict = {
"x1": [None, None, None],
"x2": [None, [None], [None]],
"x3": [None, [1], [0.5]],
"x4": [None, [None, None], [None, None]],
"x5": [None, [180, -360], [90, -180]],
}
def all_None(val):
# Check for None
if val is None:
return True
# val is not None
try:
# val may be a container
return all(all_None(el) for el in val)
except:
# val is neither None nor a container
return False
my_dict_filtered = {key: val for key, val in my_dict.items() if not all_None(val)}
print(my_dict_filtered)
Upvotes: 1
Reputation: 7238
You can write a custom recursive function to check if all the elements of the nested list are None
or not.
def is_none(a):
return all(x is None if not isinstance(x, list) else is_none(x) for x in a)
my_dict = {"x1": [None, None, None],
"x2": [None, [None], [None]],
"x3": [None, [1], [0.5]],
"x4": [None, [None, None], [None, None]],
"x5": [None, [180, -360], [90, -180]]}
new_dict = {k: v for k, v in my_dict.items() if not is_none(v)}
print(new_dict)
# {'x3': [None, [1], [0.5]], 'x5': [None, [180, -360], [90, -180]]}
Upvotes: 3
Reputation: 29635
According to the comment of Benjamin, this function should return True if all the nested list in list_input
contains the same value val_to_check
and False otherwise:
def check_val(list_input, val_to_check):
for elem in list_input:
if isinstance(elem, list):
if check_val(elem, val_to_check) == False:
return False
else:
if elem != val_to_check:
return False
return True
Upvotes: 3