私は(私の知識では)配列を分割してそれらを結合し、さらにitertoolsを使用することからすべてを試しました:
_import itertools
def oneDArray(x):
return list(itertools.chain(*x))
_
私が望む結果:
a)print oneDArray([1,[2,2,2],4]) == [1,2,2,2,4]
不思議なことに、それは
b)print oneDArray([[1, 2, 3], [4, 5, 6], [7, 8, 9]]) == [1, 2, 3, 4, 5, 6, 7, 8, 9]
質問1)パートaを希望どおりに機能させるにはどうすればよいですか(ヒントはありますか?)
質問2)上記のコードがパートaではなくパートbで機能するのはなぜですか??
リストを再帰的にループして、アイテムが反復可能かどうか(文字列も反復可能ですが、スキップするかどうか)を確認する必要があります。
itertools.chain
はすべての項目を反復可能にする必要があるため[1,[2,2,2],4]
では機能しませんが、1
と4
(整数)は反復可能ではありません。それがリストのリストであるため、それが2番目のもので機能した理由です。
>>> from collections import Iterable
def flatten(lis):
for item in lis:
if isinstance(item, Iterable) and not isinstance(item, basestring):
for x in flatten(item):
yield x
else:
yield item
>>> lis = [1,[2,2,2],4]
>>> list(flatten(lis))
[1, 2, 2, 2, 4]
>>> list(flatten([[1, 2, 3], [4, 5, 6], [7, 8, 9]]))
[1, 2, 3, 4, 5, 6, 7, 8, 9]
あらゆるレベルのネストで機能します。
>>> a = [1,[2,2,[2]],4]
>>> list(flatten(a))
[1, 2, 2, 2, 4]
他のソリューションとは異なり、これは文字列でも機能します。
>>> lis = [1,[2,2,2],"456"]
>>> list(flatten(lis))
[1, 2, 2, 2, '456']
python < 3
を使用している場合は、次の操作を実行できます。
from compiler.ast import flatten
list = [1,[2,2,2],4]
print flatten(list)
python 3.0での手動の同等物は( この回答 から取得):
def flatten(x):
result = []
for el in x:
if hasattr(el, "__iter__") and not isinstance(el, str):
result.extend(flatten(el))
else:
result.append(el)
return result
print(flatten(["junk",["nested stuff"],[],[[]]]))
リスト内包表記でも同じことができます。
list = [1,[2,2,2],4]
l = [item for sublist in list for item in sublist]
これは次と同等です:
l = [[1], [2], [3], [4], [5]]
result = []
for sublist in l:
for item in sublist:
result.append(item)
print(result)
pythonのネストされたリストから単一のリストを作成するには、次のようにするだけです。
from functools import reduce
some_list = [[14], [215, 383, 87], [298], [374], [2,3,4,5,6,7]]
single_list = reduce(lambda x,y: x+y, some_list)
print(single_list)
出力:[14, 215, 383, 87, 298, 374, 2, 3, 4, 5, 6, 7]
itertools.chain()
入力されたリストの各項目を繰り返し処理します(リンクしたドキュメントを参照してください)。整数を反復処理できないため、エラーが発生します。そのため、2番目の例では、リストにリストのみがあり、整数だけがないため、実際に整数が繰り返されることはありません。
それを機能させるには、再帰を使用できます。
>>> from collections import Iterable
>>> def flat(lst):
... for parent in lst:
... if not isinstance(i, Iterable):
... yield parent
... else:
... for child in flat(parent):
... yield child
...
>>> list(flat(([1,[2,2,2],4]))
[1, 2, 2, 2, 4]
リストのリストの1つのレベルのみになる場合、最も簡単な解決策は次のとおりです。
lis = [1,[2,2,2],"456"]
output = []
for item in lis:
if isinstance(item, (str, int, bool)):
output.append(item)
Elif isinstance(item, dict):
for i in item.items():
output.extend(i)
else:
output.extend(list(item))
私がextend(list(item))を使用した理由は、アイテム内にセットがあったとしても、問題が発生しないためです。これは、文字列、整数、ブール値、辞書、リスト、およびタプルとしてアイテムを処理します。
old_list = [1,2,3,['a','b'],4,5,6,['c','d',[11,22,33,'aa','bb','cc',[111,222,333,['aaa','bbb','ccc',[1111,2222,['aaaa','bbbb',[11111,22222]]]]]],'e']]
new_list = []
def my_fun(temp_list):
for ele in temp_list:
if type(ele) == list:
my_fun(ele)
else:
new_list.append(ele)
my_fun(old_list)
print old_list
print new_list
output:
old_list = [1, 2, 3, ['a', 'b'], 4, 5, 6, ['c', 'd', [11, 22, 33, 'aa', 'bb', 'cc', [111, 222, 333, ['aaa', 'bbb', 'ccc', [1111, 2222, ['aaaa', 'bbbb', [11111, 22222]]]]]], 'e']]
new_list = [1, 2, 3, 'a', 'b', 4, 5, 6, 'c', 'd', 11, 22, 33, 'aa', 'bb', 'cc', 111, 222, 333, 'aaa', 'bbb', 'ccc', 1111, 2222, 'aaaa', 'bbbb', 11111, 22222, 'e']
再帰を使用して、複数のネストされたリストを単一のスライスされたリストに変換します。
Itertoolsを使用しなくても実際には非常に簡単です。リストを反復処理するだけで、ループで別のリストが検出された場合は、ネストされたリストを反復処理するだけです。コードは次のとおりです。
def flatten(l):
flatList = []
for elem in l:
# if an element of a list is a list
# iterate over this list and add elements to flatList
if type(elem) == list:
for e in elem:
flatList.append(e)
else:
flatList.append(elem)
return flatList
a = [1,[2,2,2],4] # flatten(a) returns [1, 2, 2, 2, 4]
b = [[1, 2, 3], [4, 5, 6], [7, 8, 9]] # flatten(b) returns [1, 2, 3, 4, 5, 6, 7, 8, 9]