EDIT:問題はhowではなく-これは 議論 他の 質問 -問題は、fastestメソッドですか?
以前に解決策を見つけましたが、任意の長さの他のリストを含むリストを平坦化するのが最も速い解決策は何だろうと思っています。
例えば:
[1, 2, [3, 4, [5],[]], [6]]
になるでしょう:
[1,2,3,4,5,6]
レベルは無限にあります。一部のリストオブジェクトは文字列にすることができますが、出力リスト内の連続した文字にフラット化することはできません。
文字列に優しい再帰的なアプローチを次に示します。
nests = [1, 2, [3, 4, [5],['hi']], [6, [[[7, 'hello']]]]]
def flatten(container):
for i in container:
if isinstance(i, (list,Tuple)):
for j in flatten(i):
yield j
else:
yield i
print list(flatten(nests))
戻り値:
[1, 2, 3, 4, 5, 'hi', 6, 7, 'hello']
これは、速度やオーバーヘッドの使用を保証するものではありませんが、役に立つと思われる再帰的なソリューションを示しています。
haveは再帰的ではありません。実際、関数呼び出しに伴うオーバーヘッドのため、反復ソリューションの方が高速になることがよくあります。しばらく前に書いた反復バージョンは次のとおりです。
def flatten(items, seqtypes=(list, Tuple)):
for i, x in enumerate(items):
while i < len(items) and isinstance(items[i], seqtypes):
items[i:i+1] = items[i]
return items
この特定の実装のパフォーマンスはテストしていませんが、すべてのスライスの割り当てのためにそれほど大きくはないため、多くのメモリを移動する可能性があります。それでも、再帰的である必要があるとか、そのように書く方が簡単だと思い込まないでください。
この実装には、再帰的なソリューションが常に行うように、コピーを返すのではなく、リストを「インプレース」で平坦化するという利点があります。これは、メモリが不足しているときに役立ちます。フラット化されたコピーが必要な場合は、フラット化するリストの浅いコピーを渡すだけです。
flatten(mylist) # flattens existing list
newlist = flatten(mylist[:]) # makes a flattened copy
また、このアルゴリズムは再帰的ではないため、Python再帰制限によって制限されません。ただし、これは事実上決して機能しません。
この関数は、再帰を使用せずに、ネストされた反復可能なコンテナをすばやくフラット化できる必要があります。
import collections
def flatten(iterable):
iterator = iter(iterable)
array, stack = collections.deque(), collections.deque()
while True:
try:
value = next(iterator)
except StopIteration:
if not stack:
return Tuple(array)
iterator = stack.pop()
else:
if not isinstance(value, str) \
and isinstance(value, collections.Iterable):
stack.append(iterator)
iterator = iter(value)
else:
array.append(value)
約5年後、この問題についての私の意見は変わりました。これはさらに使いやすいものです。
def main():
data = [1, 2, [3, 4, [5], []], [6]]
print(list(flatten(data)))
def flatten(iterable):
iterator, sentinel, stack = iter(iterable), object(), []
while True:
value = next(iterator, sentinel)
if value is sentinel:
if not stack:
break
iterator = stack.pop()
Elif isinstance(value, str):
yield value
else:
try:
new_iterator = iter(value)
except TypeError:
yield value
else:
stack.append(iterator)
iterator = new_iterator
if __== '__main__':
main()