连接在Python列表中的列表
在python中join一个列表列表(或迭代器)的简短语法?
例如,我有一个列表如下,我想迭代a,b和c。
x = [["a","b"], ["c"]]
我能拿出的最好的如下。
result = [] [ result.extend(el) for el in x] for el in result: print el
import itertools a = [["a","b"], ["c"]] print list(itertools.chain.from_iterable(a))
如果你只深入一层,嵌套的理解也将起作用:
>>> 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']
x = [["a","b"], ["c"]] result = sum(x, [])
这被称为扁平化,并有很多实现在那里:
- 更多关于python flatten
- Python技巧
- 在Python中展平列表
这个怎么样,虽然它只能用于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)
l = [] map(l.extend, list_of_lists)
最短!
这对无限嵌套的元素recursion地工作:
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”] >>> list(iterFlatten(b)) ['A B C D']
晚了,但是…
我是python新手,来自lisp背景。 这就是我想出的(查看lulz的var名称):
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]
似乎工作。 testing:
flatten((1,2,3,(4,5,6,(7,8,(((1,2)))))))
收益:
[1, 2, 3, 4, 5, 6, 7, 8, 1, 2]
你所描述的是把列表弄平 ,用这些新的知识,你可以在Google上find很多解决scheme(没有内置的扁平化方法)。 这是其中之一,从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
性能比较:
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,但是上面的注释中的from_iterable
从from_iterable
得到的速度比map+extend
快,所以它是相当平台和input依赖的。
远离sum(big_list, [])
总是减less(被弃用到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 >>>
不幸的是,列表连接的加号运算符不能用作函数 – 或者幸运的是,如果您希望lambdaexpression式更难以提高可见性。
或者recursion操作:
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
可悲的是,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
这将recursion地压扁一个列表; 你可以这样做
result = [] [ result.extend(el) for el in x] for el in flatten(result): print el
当我不得不创build一个包含数组元素和数量的字典时,我遇到了类似的问题。 答案是相关的,因为我扁平列表,得到我需要的元素,然后做一个组和计数。 我使用Python的映射函数来产生一个元素的元组,它是数组和数组。 请注意,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])
首先,我将提取所有的“实体”集合,然后为每个实体集合迭代字典并提取名称属性。
对于单层拼合,如果你关心速度,那么在我尝试的所有条件下,这比以前的任何答案都快。 (也就是说,如果你需要结果作为一个列表,如果你只需要通过它即时迭代,那么链例子可能会更好)。它通过预先分配最终大小的列表并复制零件通过切片(这是比任何迭代器方法更低级的块拷贝):
def join(a): """Joins a sequence of sequences into a single sequence. (One-level flattening.) Eg, 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
sorting时间列表与评论:
[(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, [])
如果你需要一个列表,而不是一个生成器,使用list():
from itertools import chain x = [["a","b"], ["c"]] y = list(chain(x))