我希望编写join_lists
函数,以接受任意数量的列表并将它们连接起来。例如,如果输入为
m = [1, 2, 3]
n = [4, 5, 6]
o = [7, 8, 9]
当我调用print join_lists(m, n, o)
时,它将返回[1, 2, 3, 4, 5, 6, 7, 8, 9]
。我意识到应该在join_lists
中使用*args
作为参数,但不确定如何连接任意数量的列表。谢谢。
虽然你可以按顺序使用调用__add__
的方法,但那是非常错误的做法(首先,你会创建与输入列表数量相同的新列表,这将导致二次复杂度)。
标准工具是itertools.chain
:
def concatenate(*lists):
return itertools.chain(*lists)
或者def concatenate(*lists):
return itertools.chain.from_iterable(lists)
这将返回一个生成器,按顺序产生列表中的每个元素。如果您需要将其作为列表使用,请使用list
: list(itertools.chain.from_iterable(lists))
如果您坚持手动完成,则使用extend
:
def concatenate(*lists):
newlist = []
for l in lists: newlist.extend(l)
return newlist
实际上,不要像那样使用extend
——这仍然是低效的,因为它必须不断地扩展原始列表。"正确"的方法(其实还是错误的方法):
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
请注意,这仍然会执行与列表中总插槽数相同的复制操作。因此,这不比使用 list(chain.from_iterable(lists))
更好,并且可能更糟,因为list
可以在C级别上利用优化。
最后,这是使用 extend
的版本(次优)单行代码,使用 reduce:
concatenate = lambda *lists: reduce((lambda a,b: a.extend(b) or a),lists,[])
[None]*newlen
,就像您的示例一样,然后执行 newlist[:] = itertools.chain.from_iterable(lists)
如何?C级别的优化不能使你摆脱这个事实:在迭代所有内容之前,列表构造函数无法知道最终的长度。 - Random832list
。 - Marcin这种方法可能是使用reduce
,因为目前我感觉比较函数式:
import operator
from functools import reduce
def concatenate(*lists):
return reduce(operator.add, lists)
然而,更好的功能方法在马尔钦的回答中给出:
from itertools import chain
def concatenate(*lists):
return chain(*lists)
尽管您可以直接使用 itertools.chain(*iterable_of_lists)
,但以下是一种过程式的方法:def concatenate(*lists):
new_list = []
for i in lists:
new_list.extend(i)
return new_list
一种压缩的版本:j=lambda*x:sum(x,[])
(实际上不要使用这个版本)。
extend
来实现一行代码的版本。 - Marcinitertools.chain.from_iterable(lists)
高效吗? - rlmsstart
参数,来使用sum()
函数:def join_lists(*lists):
return sum(lists, [])
例如:
>>> join_lists([1, 2, 3], [4, 5, 6])
[1, 2, 3, 4, 5, 6]
sum()
函数在内部使用 +
还是 +=
来累加结果?如果使用其中一种,这将具有二次复杂度,而使用另一种则是线性的。 - Duncansum()
使用就地加法,它将改变起始值,这可能会破坏事物,因此它必须使用具有二次复杂度的普通加法。 - Duncan>>> 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]
>>>
def join_lists(*args):
output = []
for lst in args:
output += lst
return output
它返回一个包含所有先前列表项的新列表。对于这种列表处理,使用+符号是否不合适?
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
然后
print(join_lists(m, n, o))
将输出:
[1, 2, 3, 4, 5, 6, 7, 8, 9]
from itertools import chain
。 - Derek Veit