Flatten a list of strings and lists of strings and lists in Python
本问题已经有最佳答案,请猛点这里访问。
以前也有过类似的问题,但是这些问题的解决方案不适用于我的用例(例如,在python的列表中创建一个简单的列表,在python中扁平化一个浅列表)。我有一个字符串和列表的列表,其中嵌入的列表也可以包含字符串和列表。我想把它转换成一个简单的字符串列表,而不需要将字符串拆分成字符列表。
1 2 3 4 | import itertools list_of_menuitems = ['image10', ['image00', 'image01'], ['image02', ['image03', 'image04']]] chain = itertools.chain(*list_of_menuitems) |
结果列表:
1 | ['i', 'm', 'a', 'g', 'e', '1', '0', 'image00', 'image01', 'image02', ['image03', 'image04']] |
号
预期结果:
1 | ['image10', 'image00', 'image01', 'image02', 'image03', 'image04'] |
做这个最好的方法是什么?
经常重复的
1 2 3 4 5 6 7 8 | from collections import Iterable def flatten(coll): for i in coll: if isinstance(i, Iterable) and not isinstance(i, basestring): for subc in flatten(i): yield subc else: yield i |
还有一些版本依赖于
(请向上投票链接的答案。)
使用递归。
1 2 3 4 5 6 | def flattern(A): rt = [] for i in A: if isinstance(i,list): rt.extend(flattern(i)) else: rt.append(i) return rt |
试验:
1 2 3 4 | >>> list_of_menuitems = ['image10', ['image00', 'image01'], ['image02', ['image0 3', 'image04']]] >>> flattern(list_of_menuitems) ['image10', 'image00', 'image01', 'image02', 'image03', 'image04'] |
以下适用于字符串(并且很容易适应其他类型):
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 | def flatten_to_strings(listOfLists): """Flatten a list of (lists of (lists of strings)) for any level of nesting""" result = [] for i in listOfLists: # Only append if i is a basestring (superclass of string) if isinstance(i, basestring): result.append(i) # Otherwise call this function recursively else: result.extend(flatten_to_strings(i)) return result flatten_to_strings(list_of_menuitems) Out[2]: ['image10', 'image00', 'image01', 'image02', 'image03', 'image04'] |
这是一个通用递归展平,可用于处理应展平或不应展平的任何类型组合:
1 2 3 4 5 6 7 8 9 10 11 | import collections def generic_flatten(seq, flatten_types=(tuple,list,set),atom_types=(basestring,dict),fixtype=True): newseq = [] for item in seq: if (not isinstance(collections.Iterable)) or any(isinstance(i,t) for t in atom_types): newseq.append(item) elif any(isinstance(i,t) for t in flatten_types): # set flatten_types to (object,) or (collections.Iterable,) to disable check newseq.extend(generic_flatten(item, flatten_types, atom_types,fixtype) if fixtype and type(newseq) is not type(seq): newseq = type(seq)(newseq) return newseq |
在一个特殊的情况下,当列表项中没有包含下列定界符之一
1 2 | >>> str(list_of_menuitems).translate(None,"[]'").split(',') ['image10', ' image00', ' image01', ' image02', ' image03', ' image04'] |
我同意,这是一个肮脏的黑客,但做这项工作,没有太多的努力。