Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

concatenate an arbitrary number of lists in a function in Python

Tags:

python

list

I hope to write the join_lists function to take an arbitrary number of lists and concatenate them. For example, if the inputs are

m = [1, 2, 3]
n = [4, 5, 6]
o = [7, 8, 9]

then we I call print join_lists(m, n, o), it will return [1, 2, 3, 4, 5, 6, 7, 8, 9]. I realize I should use *args as the argument in join_lists, but not sure how to concatenate an arbitrary number of lists. Thanks.

like image 426
alittleboy Avatar asked Sep 05 '13 17:09

alittleboy


People also ask

How do you combine list values in Python?

The most conventional method to concatenate lists in python is by using the concatenation operator(+). The “+” operator can easily join the whole list behind another list and provide you with the new list as the final output as shown in the below example.

How do I append multiple lists into one?

Using extend() method to append multiple lists Here we are using the concept of list comprehension and extend() all the lists at once in the first list.


3 Answers

One way would be this (using reduce) because I currently feel functional:

import operator
from functools import reduce
def concatenate(*lists):
    return reduce(operator.add, lists)

However, a better functional method is given in Marcin's answer:

from itertools import chain
def concatenate(*lists):
    return chain(*lists)

although you might as well use itertools.chain(*iterable_of_lists) directly.

A procedural way:

def concatenate(*lists):
    new_list = []
    for i in lists:
        new_list.extend(i)
    return new_list

A golfed version: j=lambda*x:sum(x,[]) (do not actually use this).

like image 54
rlms Avatar answered Oct 05 '22 18:10

rlms


Although you can use something which invokes __add__ sequentially, that is very much the wrong thing (for starters you end up creating as many new lists as there are lists in your input, which ends up having quadratic complexity).

The standard tool is itertools.chain:

def concatenate(*lists):
    return itertools.chain(*lists)

or

def concatenate(*lists):
    return itertools.chain.from_iterable(lists)

This will return a generator which yields each element of the lists in sequence. If you need it as a list, use list: list(itertools.chain.from_iterable(lists))

If you insist on doing this "by hand", then use extend:

def concatenate(*lists):
    newlist = []
    for l in lists: newlist.extend(l)
    return newlist

Actually, don't use extend like that - it's still inefficient, because it has to keep extending the original list. The "right" way (it's still really the wrong way):

def concatenate(*lists):
    lengths = map(len,lists)
    newlen = sum(lengths)
    newlist = [None]*newlen
    start = 0
    end = 0
    for l,n in zip(lists,lengths):
        end+=n
        newlist[start:end] = list
        start+=n
    return newlist

http://ideone.com/Mi3UyL

You'll note that this still ends up doing as many copy operations as there are total slots in the lists. So, this isn't any better than using list(chain.from_iterable(lists)), and is probably worse, because list can make use of optimisations at the C level.


Finally, here's a version using extend (suboptimal) in one line, using reduce:

concatenate = lambda *lists: reduce((lambda a,b: a.extend(b) or a),lists,[])
like image 31
Marcin Avatar answered Oct 05 '22 19:10

Marcin


You can use sum() with an empty list as the start argument:

def join_lists(*lists):
    return sum(lists, [])

For example:

>>> join_lists([1, 2, 3], [4, 5, 6])
[1, 2, 3, 4, 5, 6]
like image 26
Andrew Clark Avatar answered Oct 05 '22 20:10

Andrew Clark