3

I have a list of tuples that reads as such:

>>>myList
[(), (), ('',), ('c', 'e'), ('ca', 'ea'), ('d',), ('do',), ('dog', 'ear', 'eat', 'cat', 'car'), ('dogs', 'cars', 'done', 'eats', 'cats', 'ears'), ('don',)]

And I would like it to read as such:

>>>myList
[('',), ('c', 'e'), ('ca', 'ea'), ('d',), ('do',), ('dog', 'ear', 'eat', 'cat', 'car'), ('dogs', 'cars', 'done', 'eats', 'cats', 'ears'), ('don',)]

i.e. I would like to remove the empty tuples () from the list. While doing this I want to preserve the tuple ('',). I cannot seem to find a way to remove these empty tuples from the list.

I have tried myList.remove(()) and using a for loop to do it, but either that doesn't work or I am getting the syntax wrong. Any help would be appreciated.

ilikemustard
  • 45
  • 1
  • 5
  • 1
    An important thing to note there is that empty tuples ``()`` evaluate to ``False`` in a boolean context (e.g. ``if my_tuple:``). Tuples containing only empty/falsy values (e.g. ``('',)`` or ``(None, ())``), however, evaluate to ``True``. – Max Noel Dec 06 '13 at 01:48

4 Answers4

10

You can filter 'empty' values:

filter(None, myList)

or you can use a list comprehension. On Python 3, filter() returns a generator; the list comprehension returns a list on either Python 2 or 3:

[t for t in myList if t]

If your list contains more than just tuples, you could test for empty tuples explicitly:

[t for t in myList if t != ()]

Python 2 demo:

>>> myList = [(), (), ('',), ('c', 'e'), ('ca', 'ea'), ('d',), ('do',), ('dog', 'ear', 'eat', 'cat', 'car'), ('dogs', 'cars', 'done', 'eats', 'cats', 'ears'), ('don',)]
>>> filter(None, myList)
[('',), ('c', 'e'), ('ca', 'ea'), ('d',), ('do',), ('dog', 'ear', 'eat', 'cat', 'car'), ('dogs', 'cars', 'done', 'eats', 'cats', 'ears'), ('don',)]
>>> [t for t in myList if t]
[('',), ('c', 'e'), ('ca', 'ea'), ('d',), ('do',), ('dog', 'ear', 'eat', 'cat', 'car'), ('dogs', 'cars', 'done', 'eats', 'cats', 'ears'), ('don',)]
>>> [t for t in myList if t != ()]
[('',), ('c', 'e'), ('ca', 'ea'), ('d',), ('do',), ('dog', 'ear', 'eat', 'cat', 'car'), ('dogs', 'cars', 'done', 'eats', 'cats', 'ears'), ('don',)]

Of these options, the filter() function is fastest:

>>> timeit.timeit('filter(None, myList)', 'from __main__ import myList')
0.637274980545044
>>> timeit.timeit('[t for t in myList if t]', 'from __main__ import myList')
1.243359088897705
>>> timeit.timeit('[t for t in myList if t != ()]', 'from __main__ import myList')
1.4746298789978027

On Python 3, stick to the list comprehension instead:

>>> timeit.timeit('list(filter(None, myList))', 'from __main__ import myList')
1.5365421772003174
>>> timeit.timeit('[t for t in myList if t]', 'from __main__ import myList')
1.29734206199646
Martijn Pieters
  • 1,048,767
  • 296
  • 4,058
  • 3,343
7
myList = [x for x in myList if x != ()]
Hyperboreus
  • 31,997
  • 9
  • 47
  • 87
3

Use a list comprehension to filter out the empty tuples:

>>> myList = [(), (), ('',), ('c', 'e'), ('ca', 'ea'), ('d',), ('do',), ('dog', 'ear', 'eat', 'cat', 'car'), ('dogs', 'cars', 'done', 'eats', 'cats', 'ears'), ('don',)]
>>> myList = [x for x in myList if x]
>>> myList
[('',), ('c', 'e'), ('ca', 'ea'), ('d',), ('do',), ('dog', 'ear', 'eat', 'cat', 'car'), ('dogs', 'cars', 'done', 'eats', 'cats', 'ears'), ('don',)]
>>>

This works because empty tuples evaluate to False in Python.

  • Thanks! This is actually the answer I used in my code since it looks cleanest. – ilikemustard Dec 06 '13 at 00:18
  • @ilikemustard - You're welcome! However, if my answer was the one you used, then I ask that you please don't forget to [accept it](http://meta.stackexchange.com/questions/5234/how-does-accepting-an-answer-work/5235#5235). Accepting answers lets future people know that the question is answered. –  Dec 06 '13 at 00:21
  • Yeah good idea! I am new to asking questions so I'm still getting the hang of it. Though this answer answered my question perfectly, there was another more thorough answer that I think was slightly more helpful so I accepted that. Sorry to disappoint, and thanks a ton for the answer! Have a nice day. – ilikemustard Dec 08 '13 at 01:06
  • 1
    Hey that's fine. The important thing is that the question is answered. Besides, I even think that Pieter's answer deserved the acceptance. He clearly put in a lot more effort than I did. –  Dec 08 '13 at 02:19
2

Explicit is better than implicit

I find this one is more readable and not ambiguous by specifying clearly what function of the filter is. So clearly we want to remove those empty tuple which is ().

def filter_empty_tuple(my_tuple_list):
    return filter(lambda x: x != (), my_tuple_list)

# convert to list
def filter_empty_tuple_to_list(my_tuple_list):
    return list(filter(lambda x: x != (), my_tuple_list))

Perhaps it would be good if you don't convert them into a list and use it as generator. See this question when deciding which to use

Community
  • 1
  • 1