Deleting an entire list from list of lists

Viewed 374

I have a list of lists as follows :

g = [
    ["a","?","?","?","?","?","?"],
    ["?","b","?","?","?","?","?"],
    ["?","?","?","?","?","?","?"]
]

I want to iterate through this list and delete the list which contains all "?", which is the last list in this list of lists. I've tried pop() , del and several other operation but nothing seems to be working so far.

Here's what I've written for this part :

for x in g:
    if x.count("?") == 6:
        g.pop(g.index(x))

It doesn't remove the list but removes one "?" from the last list. Can anyone please guide me here.

6 Answers

You should leverage set here:

In [152]: X = [["a","?","?","?","?","?","?"],["?","b","?","?","?","?","?"],["?","?","?","?","?","?","?"]]

In [153]: [l for l in X if set(l) != {"?"}]
Out[153]: [['a', '?', '?', '?', '?', '?', '?'], ['?', 'b', '?', '?', '?', '?', '?']]

set(l) gets the unique values of the list and makes a set out of it, comparing the resulting set with {"?"} would suffice as you want to drop the list with all ?s.

Try this list comprehension:

X = [["a","?","?","?","?","?","?"],["?","b","?","?","?","?","?"],["?","?","?","?","?","?","?"]]

print([l for l in X if l.count("?") == len(l)])

Output:

[['a', '?', '?', '?', '?', '?', '?'], ['?', 'b', '?', '?', '?', '?', '?']]

As an added bonus, it is 2x faster than @heemayl's answer.

May be this would help!

[x for i,x in enumerate(X) if ''.join(x).replace('?','')]

output:

[['a', '?', '?', '?', '?', '?', '?'], ['?', 'b', '?', '?', '?', '?', '?']]

In case list comprehensions are not very clear as in the answers you have received, an alternative can have this form;

l = [['a', '?'], ['?', '?']]

result = []
for i in l:
    if ('?' in i) and (set(i) == {'?'}):
        continue
    result.append(i)

Let's use Lists comprehensions to solve this -

all([True, True, True)] 
   True
all(True, True, False)
   False

Thus we compare each element of sub-lists to '?' and in case they are '?', then we return True and finally apply all() function to the sub-lists.

g_out = [i for i in g if all([j=='?' for j in i]) == False]
print(g_out)
    [['a', '?', '?', '?', '?', '?', '?'], ['?', 'b', '?', '?', '?', '?', '?']]

You can use filter with lambda functions as well:

func = lambda x: x.count("?") != len(x)
new_g = list(filter(func, g))
Related