简体   繁体   English

在Python中连接函数中的任意数量的列表

[英]concatenate an arbitrary number of lists in a function in Python

I hope to write the join_lists function to take an arbitrary number of lists and concatenate them. 我希望编写join_lists函数来获取任意数量的列表并将它们连接起来。 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] . 然后我们调用print join_lists(m, n, o) ,它将返回[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. 我意识到我应该使用*args作为join_lists的参数,但不确定如何连接任意数量的列表。 Thanks. 谢谢。

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). 虽然你可以使用顺序调用__add__东西,但这是非常错误的事情(对于初学者,你最终会创建尽可能多的新列表,因为输入中有列表,最终会产生二次复杂度)。

The standard tool is itertools.chain : 标准工具是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)) 如果您需要它作为列表,请使用listlist(itertools.chain.from_iterable(lists))

If you insist on doing this "by hand", then use extend : 如果你坚持“手工”这样做,那么使用 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. 实际上,不要像那样使用extend - 它仍然效率低下,因为它必须不断扩展原始列表。 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 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. 所以,这并不比使用list(chain.from_iterable(lists))更好,并且可能更糟,因为list可以利用C级别的优化。


Finally, here's a version using extend (suboptimal) in one line, using reduce: 最后,这里是一个使用extend (suboptimal)在一行中的版本,使用reduce:

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

One way would be this (using reduce ) because I currently feel functional: 一种方法是这样(使用reduce ),因为我目前感觉功能:

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: 然而,在Marcin的答案中给出了一种更好的功能方法:

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

although you might as well use itertools.chain(*iterable_of_lists) directly. 虽然你不妨直接使用itertools.chain(*iterable_of_lists)

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). 高尔夫版本: j=lambda*x:sum(x,[]) (实际上不使用此)。

You can use sum() with an empty list as the start argument: 您可以将sum()与空列表一起用作start参数:

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

For example: 例如:

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

This seems to work just fine: 这似乎工作得很好:

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

It returns a new list with all the items of the previous lists. 它返回一个包含先前列表中所有项目的新列表。 Is using + not appropriate for this kind of list processing? 使用+不适合这种列表处理吗?

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]
>>> 

Or you could be logical instead, making a variable (here 'z') equal to the first list passed to the 'join_lists' function then assigning the items in the list (not the list itself) to a new list to which you'll then be able add the elements of the other lists: 或者你可能是合乎逻辑的,使变量(这里'z')等于传递给'join_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) print(join_lists(m,n,o)

would output: 输出:

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM