如何在保留一些嵌套的同时展平列表(在 python 中)
how to flatten lists while leaving some nesting (in python)
我有一个包含字符串列表的列表列表,像这样(代表文本的章节、段落和句子):
[ [[ ['chp1p1s1'], ['chp1p1s2'], ['chp1p1s3'] ],
[ ['chp1p2s1'], ['chp1p2s2'], ['chp1p2s3'] ]],
[[ ['chp2p1s1'], ['chp2p1s2'], ['chp2p1s3'] ],
[ ['chp2p2s1'], ['chp2p2s2'], ['chp2p2s3'] ]] ]
我知道如何完全展平这个列表(例如 [x for y in z for x in y]
),但我想做的是部分展平它,最终看起来像这样:
[ [ ['chp1p1s1'], ['chp1p1s2'], ['chp1p1s3'],
['chp1p2s1'], ['chp1p2s2'], ['chp1p2s3'] ],
[ ['chp2p1s1'], ['chp2p1s2'], ['chp2p1s3'],
['chp2p2s1'], ['chp2p2s2'], ['chp2p2s3'] ] ]
我设法通过一些 for 循环解决了这个问题:
semiflattend_list=list()
for chapter in chapters:
senlist=list()
for paragraph in chapter:
for sentences in paragraph:
senlist.append(sentences)
semiflattend_list.append(senlist)
但我想知道是否有更好、更短的解决方案? (我不认为 zip
是一种可行的方法,因为我的列表大小不同。)
我能看到的最简单的更改是使用 itertools.chain
方法:
q = [
[[ ['chp1p1s1'], ['chp1p1s2'], ['chp1p1s3'] ],
[ ['chp1p2s1'], ['chp1p2s2'], ['chp1p2s3'] ]],
[[ ['chp2p1s1'], ['chp2p1s2'], ['chp2p1s3'] ],
[ ['chp2p2s1'], ['chp2p2s2'], ['chp2p2s3'] ]]
]
r = [list(itertools.chain(*g)) for g in q]
print(r)
[[['chp1p1s1'], ['chp1p1s2'], ['chp1p1s3'], ['chp1p2s1'], ['chp1p2s2'], ['chp1p2s3']],
[['chp2p1s1'], ['chp2p1s2'], ['chp2p1s3'], ['chp2p2s1'], ['chp2p2s2'], ['chp2p2s3']]]
那么,[list(itertools.chain(*g)) for g in q]
是什么意思:
# If I only had this
[g for g in q]
# I would get the same I started with.
# What I really want is to expand the nested lists
# * before an iterable (basically) converts the iterable into its parts.
func foo(bar, baz):
print( bar + " " + baz )
lst = ["cat", "dog"]
foo(*lst) # prints "cat dog"
# itertools.chain accepts an arbitrary number of lists, and then outputs
# a generator of the results:
c = itertools.chain([1],[2])
# c is now <itertools.chain object at 0x10e1fce10>
# You don't want an generator though, you want a list. Calling `list` converts that:
o = list( c )
# o is now [1,2]
# Now, together:
myList = [[2],[3]]
flattened = list(itertools.chain(*myList))
# flattened is now [2,3]
我有一个包含字符串列表的列表列表,像这样(代表文本的章节、段落和句子):
[ [[ ['chp1p1s1'], ['chp1p1s2'], ['chp1p1s3'] ],
[ ['chp1p2s1'], ['chp1p2s2'], ['chp1p2s3'] ]],
[[ ['chp2p1s1'], ['chp2p1s2'], ['chp2p1s3'] ],
[ ['chp2p2s1'], ['chp2p2s2'], ['chp2p2s3'] ]] ]
我知道如何完全展平这个列表(例如 [x for y in z for x in y]
),但我想做的是部分展平它,最终看起来像这样:
[ [ ['chp1p1s1'], ['chp1p1s2'], ['chp1p1s3'],
['chp1p2s1'], ['chp1p2s2'], ['chp1p2s3'] ],
[ ['chp2p1s1'], ['chp2p1s2'], ['chp2p1s3'],
['chp2p2s1'], ['chp2p2s2'], ['chp2p2s3'] ] ]
我设法通过一些 for 循环解决了这个问题:
semiflattend_list=list()
for chapter in chapters:
senlist=list()
for paragraph in chapter:
for sentences in paragraph:
senlist.append(sentences)
semiflattend_list.append(senlist)
但我想知道是否有更好、更短的解决方案? (我不认为 zip
是一种可行的方法,因为我的列表大小不同。)
我能看到的最简单的更改是使用 itertools.chain
方法:
q = [
[[ ['chp1p1s1'], ['chp1p1s2'], ['chp1p1s3'] ],
[ ['chp1p2s1'], ['chp1p2s2'], ['chp1p2s3'] ]],
[[ ['chp2p1s1'], ['chp2p1s2'], ['chp2p1s3'] ],
[ ['chp2p2s1'], ['chp2p2s2'], ['chp2p2s3'] ]]
]
r = [list(itertools.chain(*g)) for g in q]
print(r)
[[['chp1p1s1'], ['chp1p1s2'], ['chp1p1s3'], ['chp1p2s1'], ['chp1p2s2'], ['chp1p2s3']],
[['chp2p1s1'], ['chp2p1s2'], ['chp2p1s3'], ['chp2p2s1'], ['chp2p2s2'], ['chp2p2s3']]]
那么,[list(itertools.chain(*g)) for g in q]
是什么意思:
# If I only had this
[g for g in q]
# I would get the same I started with.
# What I really want is to expand the nested lists
# * before an iterable (basically) converts the iterable into its parts.
func foo(bar, baz):
print( bar + " " + baz )
lst = ["cat", "dog"]
foo(*lst) # prints "cat dog"
# itertools.chain accepts an arbitrary number of lists, and then outputs
# a generator of the results:
c = itertools.chain([1],[2])
# c is now <itertools.chain object at 0x10e1fce10>
# You don't want an generator though, you want a list. Calling `list` converts that:
o = list( c )
# o is now [1,2]
# Now, together:
myList = [[2],[3]]
flattened = list(itertools.chain(*myList))
# flattened is now [2,3]