2

I am trying to write a function to take in any number of different lists or tuples as arguments and return one big list.

def addify(*args):
    big_list = list()
    for iterable in args:
        if isinstance(iterable, tuple):
            big_list.extend(list(iterable))
        else:
            big_list.extend(iterable)
    return big_list

>>> print addify((1,2,3), [2, 5, 3], (3,1,3), [3, 2344, 3])
[1, 2, 3, 2, 5, 3, 3, 1, 3, 3, 2344, 3]

I was learning about args and kwargs, and my code is working all right, but this seems like too much code for something so simple.

There must be a better way than writing a long function to check if an argument is a tuple and if it is add convert it to a list and then add it on. That just seems bloated.

Community
  • 1
  • 1
Fin Newt
  • 25
  • 4

2 Answers2

4

itertools.chain is what you are looking for:

>>> from itertools import chain
>>> print list(chain((1,2,3), [2, 5, 3], (3,1,3), [3, 2344, 3]))
[1, 2, 3, 2, 5, 3, 3, 1, 3, 3, 2344, 3]

Note: Calling list is necessary if you want a list instead of a itertools.chain object.

Fin Newt
  • 25
  • 4
David Greydanus
  • 2,551
  • 1
  • 23
  • 42
3

This functionality is already included in Python via itertools.chain:

>>> from itertools import chain
>>> def addify(*args):
...     return list(chain(*args))
... 
>>> addify((1,2,3), [2, 5, 3], (3,1,3), [3, 2344, 3])
[1, 2, 3, 2, 5, 3, 3, 1, 3, 3, 2344, 3]

That, or as @Navith said, you could use itertools.chain.from_iterable:

>>> from itertools import chain
>>> def addify(*args):
...     return list(chain.from_iterable(args))
... 
>>> addify((1,2,3), [2, 5, 3], (3,1,3), [3, 2344, 3])
[1, 2, 3, 2, 5, 3, 3, 1, 3, 3, 2344, 3]

Note however that you need to call list() on both because they return iterators by default:

>>> chain((1,2,3), [2, 5, 3], (3,1,3), [3, 2344, 3])
<itertools.chain object at 0x04829390>
>>> chain.from_iterable([(1,2,3), [2, 5, 3], (3,1,3), [3, 2344, 3]])
<itertools.chain object at 0x048293D0>

Which might actually be a good thing if you do not need all of the items right up front.

  • Jinx Dude :-\. But do you really need to put the call to chain in a function? – David Greydanus May 29 '15 at 19:09
  • No, you can just do `list(chain(...))`. I was only keeping the OP's function so the example was clearer. –  May 29 '15 at 19:12
  • [`chain.from_iterable(iterables)`](https://docs.python.org/3/library/itertools.html#itertools.chain.from_iterable) is preferable to `chain(*iterables)` for potentially infinite iterators. – Navith May 29 '15 at 19:15
  • @Navith - I was actually just about to add `chain.from_iterable` to my answer. Thanks for the tip though. :) –  May 29 '15 at 19:21