在 python 中连接列表列表[重复]
- 2025-02-18 09:23:00
- admin 原创
- 71
问题描述:
在 python 中将列表列表合并为单个列表(或迭代器)的简短语法是什么?
例如,我有如下列表,并且我想迭代 a、b 和 c。
x = [["a","b"], ["c"]]
我能想到的最好的办法如下。
result = []
[ result.extend(el) for el in x]
for el in result:
print el
解决方案 1:
import itertools
a = [['a','b'], ['c']]
print(list(itertools.chain.from_iterable(a)))
这给出
['a', 'b', 'c']
解决方案 2:
x = [["a","b"], ["c"]]
result = sum(x, [])
解决方案 3:
如果你只深入一层,嵌套理解也能起作用:
>>> x = [["a","b"], ["c"]]
>>> [inner
... for outer in x
... for inner in outer]
['a', 'b', 'c']
将其合并为一行,即可:
>>> [j for i in x for j in i]
['a', 'b', 'c']
解决方案 4:
flat_list = []
map(flat_list.extend, list_of_lists)
最短!
解决方案 5:
如果您需要列表而不是生成器,请使用list():
from itertools import chain
x = [["a","b"], ["c"]]
y = list(chain(*x))
解决方案 6:
这被称为扁平化,并且存在多种实现方式。
这样怎么样,尽管它只适用于 1 级深度嵌套:
>>> x = [["a","b"], ["c"]]
>>> for el in sum(x, []):
... print el
...
a
b
c
从这些链接来看,显然最完整、最快速、最优雅等的实现如下:
def flatten(l, ltypes=(list, tuple)):
ltype = type(l)
l = list(l)
i = 0
while i < len(l):
while isinstance(l[i], ltypes):
if not l[i]:
l.pop(i)
i -= 1
break
else:
l[i:i + 1] = l[i]
i += 1
return ltype(l)
解决方案 7:
性能比较:
import itertools
import timeit
big_list = [[0]*1000 for i in range(1000)]
timeit.repeat(lambda: list(itertools.chain.from_iterable(big_list)), number=100)
timeit.repeat(lambda: list(itertools.chain(*big_list)), number=100)
timeit.repeat(lambda: (lambda b: map(b.extend, big_list))([]), number=100)
timeit.repeat(lambda: [el for list_ in big_list for el in list_], number=100)
[100*x for x in timeit.repeat(lambda: sum(big_list, []), number=1)]
制作:
>>> import itertools
>>> import timeit
>>> big_list = [[0]*1000 for i in range(1000)]
>>> timeit.repeat(lambda: list(itertools.chain.from_iterable(big_list)), number=100)
[3.016212113769325, 3.0148865239060227, 3.0126415732791028]
>>> timeit.repeat(lambda: list(itertools.chain(*big_list)), number=100)
[3.019953987082083, 3.528754223385439, 3.02181439266457]
>>> timeit.repeat(lambda: (lambda b: map(b.extend, big_list))([]), number=100)
[1.812084445152557, 1.7702404451095965, 1.7722977998725362]
>>> timeit.repeat(lambda: [el for list_ in big_list for el in list_], number=100)
[5.409658160700605, 5.477502077679354, 5.444318360412744]
>>> [100*x for x in timeit.repeat(lambda: sum(big_list, []), number=1)]
[399.27587954973444, 400.9240571138051, 403.7521153804846]
这是在 Windows XP 32 位上使用 Python 2.7.1 的情况,但上面评论中的 @temotofrom_iterable
比 更快map+extend
,因此它非常依赖于平台和输入。
远离sum(big_list, [])
解决方案 8:
这对于无限嵌套的元素以递归方式起作用:
def iterFlatten(root):
if isinstance(root, (list, tuple)):
for element in root:
for e in iterFlatten(element):
yield e
else:
yield root
结果:
>>> b = [["a", ("b", "c")], "d"]
>>> 列表(iterFlatten(b))
[‘a’,‘b’,‘c’,‘d’]
解决方案 9:
参加聚会迟到了但是......
我是 Python 新手,有 Lisp 背景。这是我想到的(查看 lulz 的变量名称):
def flatten(lst):
if lst:
car,*cdr=lst
if isinstance(car,(list,tuple)):
if cdr: return flatten(car) + flatten(cdr)
return flatten(car)
if cdr: return [car] + flatten(cdr)
return [car]
似乎有效。测试:
flatten((1,2,3,(4,5,6,(7,8,(((1,2)))))))
返回:
[1, 2, 3, 4, 5, 6, 7, 8, 1, 2]
解决方案 10:
您所描述的内容称为扁平化列表,有了这些新知识,您将能够在 Google 上找到许多解决方案(没有内置的扁平化方法)。以下是其中之一,来自http://www.daniel-lemire.com/blog/archives/2006/05/10/flattening-lists-in-python/:
def flatten(x):
flat = True
ans = []
for i in x:
if ( i.__class__ is list):
ans = flatten(i)
else:
ans.append(i)
return ans
解决方案 11:
对于单级扁平化,如果您关心速度,那么在我尝试的所有条件下,这比以前任何答案都快。 (也就是说,如果您需要将结果作为列表。 如果您只需要动态地迭代它,那么链式示例可能更好。)它的工作原理是预先分配最终大小的列表并通过切片复制部分(这是比任何迭代器方法都低级别的块复制):
def join(a):
"""Joins a sequence of sequences into a single sequence. (One-level flattening.)
E.g., join([(1,2,3), [4, 5], [6, (7, 8, 9), 10]]) = [1,2,3,4,5,6,(7,8,9),10]
This is very efficient, especially when the subsequences are long.
"""
n = sum([len(b) for b in a])
l = [None]*n
i = 0
for b in a:
j = i+len(b)
l[i:j] = b
i = j
return l
带评论的排序时间列表:
[(0.5391559600830078, 'flatten4b'), # join() above.
(0.5400412082672119, 'flatten4c'), # Same, with sum(len(b) for b in a)
(0.5419249534606934, 'flatten4a'), # Similar, using zip()
(0.7351131439208984, 'flatten1b'), # list(itertools.chain.from_iterable(a))
(0.7472689151763916, 'flatten1'), # list(itertools.chain(*a))
(1.5468521118164062, 'flatten3'), # [i for j in a for i in j]
(26.696547985076904, 'flatten2')] # sum(a, [])
解决方案 12:
总是有reduce(被functools弃用):
>>> x = [ [ 'a', 'b'], ['c'] ]
>>> for el in reduce(lambda a,b: a+b, x, []):
... print el
...
__main__:1: DeprecationWarning: reduce() not supported in 3.x; use functools.reduce()
a
b
c
>>> import functools
>>> for el in functools.reduce(lambda a,b: a+b, x, []):
... print el
...
a
b
c
>>>
不幸的是,列表连接的加号运算符不能用作函数——或者幸运的是,如果您喜欢 lambda 变得丑陋以提高可见性。
解决方案 13:
或者递归操作:
def flatten(input):
ret = []
if not isinstance(input, (list, tuple)):
return [input]
for i in input:
if isinstance(i, (list, tuple)):
ret.extend(flatten(i))
else:
ret.append(i)
return ret
解决方案 14:
遗憾的是,Python 没有简单的方法来展平列表。试试这个:
def flatten(some_list):
for element in some_list:
if type(element) in (tuple, list):
for item in flatten(element):
yield item
else:
yield element
这将递归地展平列表;然后你可以这样做
result = []
[ result.extend(el) for el in x]
for el in flatten(result):
print el
解决方案 15:
当我必须创建一个包含数组元素及其计数的字典时,我遇到了类似的问题。答案是相关的,因为我展平了一个列表列表,获取我需要的元素,然后进行分组和计数。我使用 Python 的 map 函数生成一个元素元组及其计数,然后对数组进行 groupby。请注意,groupby 将数组元素本身作为 keyfunc。作为一个相对较新的 Python 程序员,我发现它对我来说更容易理解,同时也是 Pythonic。
在我讨论代码之前,这里有一个我必须先展平的数据样本:
{ "_id" : ObjectId("4fe3a90783157d765d000011"), "status" : [ "opencalais" ],
"content_length" : 688, "open_calais_extract" : { "entities" : [
{"type" :"Person","name" : "Iman Samdura","rel_score" : 0.223 },
{"type" : "Company", "name" : "Associated Press", "rel_score" : 0.321 },
{"type" : "Country", "name" : "Indonesia", "rel_score" : 0.321 }, ... ]},
"title" : "Indonesia Police Arrest Bali Bomb Planner", "time" : "06:42 ET",
"filename" : "021121bn.01", "month" : "November", "utctime" : 1037836800,
"date" : "November 21, 2002", "news_type" : "bn", "day" : "21" }
这是来自 Mongo 的查询结果。下面的代码展平了此类列表的集合。
def flatten_list(items):
return sorted([entity['name'] for entity in [entities for sublist in
[item['open_calais_extract']['entities'] for item in items]
for entities in sublist])
首先,我将提取所有“实体”集合,然后对于每个实体集合,遍历字典并提取名称属性。
扫码咨询,免费领取项目管理大礼包!