Concatenate an arbitrary number of lists in a function in Python

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

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

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

+6
source share
6 answers

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

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

However, Marcin's answer provides the best functional method:

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

although you can also use itertools.chain(*iterable_of_lists) directly.

Procedural method:

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

Golf: j=lambda*x:sum(x,[]) (this is not actually used).

+8
source

Although you can use what calls __add__ sequence, this is not at all what you need (for beginners, you create as many new lists as there are lists in your input, which ends in 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 that issues each element of the lists in sequence. If you need it, use list : list(itertools.chain.from_iterable(lists))

If you insist on doing this manually, use extend :

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

Strike>

Actually, do not use extend like this - it is still inefficient because it must continue to expand the original list. The "correct" way (this is still not the case):

 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 will notice that this still ends up with as many copy operations as there are full slots in the list. So this is no better than using list(chain.from_iterable(lists)) and probably worse because list can use C level optimization.


Finally, here is the version using extend (suboptimal) on one line, using the abbreviation:

 concatenate = lambda *lists: reduce((lambda a,b: a.extend(b) or a),lists,[]) 
+13
source

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

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

For instance:

 >>> join_lists([1, 2, 3], [4, 5, 6]) [1, 2, 3, 4, 5, 6] 
+3
source

Everything seems to work fine:

 def join_lists(*args): output = [] for lst in args: output += lst return output 

It returns a new list with all the elements of previous lists. Is using + not suitable for this kind of list processing?

0
source

Another way:

 >>> m = [1, 2, 3] >>> n = [4, 5, 6] >>> o = [7, 8, 9] >>> p = [] >>> for (i, j, k) in (m, n, o): ... p.append(i) ... p.append(j) ... p.append(k) ... >>> p [1, 2, 3, 4, 5, 6, 7, 8, 9] >>> 
-1
source

Or you could be logical instead, by making the variable (here "z") equal to the first list passed to the join_lists function, then assigning items in the list (not the list itself) to the new list, into which you can add items from other lists:

 m = [1, 2, 3] n = [4, 5, 6] o = [7, 8, 9] def join_lists(*x): z = [x[0]] for i in range(len(z)): new_list = z[i] for item in x: if item != z: new_list += (item) return new_list 

then

print (join_lists (m, n, o)

outputs:

[1, 2, 3, 4, 5, 6, 7, 8, 9]

-1
source

Source: https://habr.com/ru/post/953261/


All Articles