如何將多維list降到一維,使用環境為python3?

需要降維的列表大概是這樣的,希望能夠實現成【562,678,723,.....】,用flatten()的話只能降一級,網上查到的一些方法不太適用,想請教一下,謝謝


貢獻一個生成器版本:

def flatten(a):
for each in a:
if not isinstance(each, list):
yield each
else:
yield from flatten(each)

if __name__ == "__main__":
a = [1, [2, [3, [4]]], 5]
print(list(flatten(a)))

python3 ans.py
[1, 2, 3, 4, 5]

這個寫法可以直接擴展到一切iterable,例如:

from collections import Iterable

def flattern(a):
for each in a:
if not isinstance(each, Iterable) or isinstance(each, str):
yield each
else:
yield from flattern(each)

if __name__ == "__main__":
a = [1, (2, [3, range(100, 500, 100)]), tuple([5, 6]), ["abcd"]]
print(list(flattern(a)))

python3 ans.py
[1, 2, 3, 100, 200, 300, 400, 5, 6, "abcd"]

只要對str的特殊情況稍加處理,就能拍平任何嵌套的iterable


看到有些人不知道 __str__方法的代價還在那裡胡亂用我就想笑。

會前序訪問一遍所有的元素再合併成字元串,這個過程用列表解析已經可以出結果了。

在那裡繼續用re什麼的處理字元串還用出優越感了。

這個東西遞歸實現就三行代碼,加個速優化六七行,非遞歸實現稍微長一點。

這個東西恰好昨天需要就做了,所有版本的,遞歸惰性的,遞歸嚴格的,非遞歸惰性的,非遞歸嚴格的。因為while循環在python里是低效的,所以在遞歸深度較小時並不建議使用非遞歸版本。

那種真的不懂python還在那裡python吹(實際上是黑)的還是稍微看一下。

https://github.com/thautwarm/flowpython/blob/master/flowpython/fp.py


看了一下好多答案都是有限制的,比如只針對數字處理、只針對List處理。

獻上自己用的一個「終極版本」,可以應對數字、字元串、列表、Tuple......

# 生成器版本
def flatten(lst):
for item in lst:
if isinstance(item, collections.Iterable) and not isinstance(item, (str, bytes)):
yield from flatten(item)
else:
yield item

# 結果:
In [52]: list(flatten([[1, 2, 3], [4, 5, 6], [7], (5, 6), (("a", 777), "BCD", 6, "999"), [[8, 9]]]))
Out[52]: [1, 2, 3, 4, 5, 6, 7, 5, 6, "a", 777, "BCD", 6, "999", 8, 9]

# 普通版本
def flatten(lst):
result = []
def fly(lst):
for item in lst:
if isinstance(item, collections.Iterable) and not isinstance(item, (str, bytes)):
fly(item)
else:
result.append(item)

fly(lst)
return result

# 結果:
In [55]: flatten([[1, 2, 3], [4, 5, 6], [7], (5, 6), (("a", 777), "BCD", 6, "999"), [[8, 9]]])
Out[55]: [1, 2, 3, 4, 5, 6, 7, 5, 6, "a", 777, "BCD", 6, "999", 8, 9]

兩個版本,一個生成器,一個普通版。

希望對大家與題主有幫助。


嗯。。。幾乎可以無視維數了吧:-)


看了很多答案各種酷炫啊,如果你用Python 2.x,我告訴你只需要一行就能搞定這件事情:

&>&>&> from compiler.ast import flatten
&>&>&> l = [1, [2, [3, [4, [5, 6], 7], 8], 9], 10]
&>&>&> flatten(l)
[1, 2, 3, 4, 5, 6, 7, 8, 9, 10]

看看他是怎麼實現的吧:

def flatten(seq):
l = []
for elt in seq:
t = type(elt)
if t is tuple or t is list:
for elt2 in flatten(elt):
l.append(elt2)
else:
l.append(elt)
return l


a = [[1,2,[2, 4, 5, [1, 2, 4, [3, 4, 5]]]], [1, 2, 4, [3, 4]]]

def flat(a):
b = []
for each in a:
if not isinstance(each, list):
b.append(each)
else:
b.extend(flat(each))
return b

print(flat(a))


《Python cookbook》第三版里就有關於展開嵌套序列的例子。

from collections import Iterable

def flatten(items, ignore_types=(str, bytes)):
for x in items:
if isinstance(x, Iterable) and not isinstance(x, igore_types):
yield from flatten(x)
else:
yield x

這個解法在判斷時使用了isinstance(x, Iterable),而不是isinstance(x, list),這樣對於任何可迭代對象都可以展開,而不是只有list。如:

items = [1, 2, [3, 4], (5, 6, 7), 8]
print(list(flatten(items)))
&>&>&>[1, 2, 3, 4, 5, 6, 7, 8]

當然函數另一個參數ignore_types可以指定不需要展開的可迭代對象。下面的例子里你需要展開的列表中含有一個字典,如果使用默認參數,結果可能不是你想要的。

items = [1, 2, 3, {"a":4, "b":5}, 6, 7]
print(list(flatten(items)))
&>&>&>[1, 2, 3, "a", "b", 6, 7]

print(list(flatten(items, ignore_type=dict)))
&>&>&>[1, 2, 3, {"a": 4, "b": 5}, 6, 7]

最後這個答案值得一提的還有使用了 yield from 來進行遞歸,讓整個函數非常簡潔優美。如果對yield from 語句不熟的可以看看《流暢的Python》里流程式控制制那一章,裡面有更多關於yield 語句的介紹。


哪需要生成器、遞歸什麼的,,

簡單問題暴力一點好了

In [82]: a = [[], 1, [20, 300], [[4000, 50000, 600000]]]
...: b = str(a).replace("[", "").replace("]", "").replace(" ", "")
...: c = [eval(i) for i in b.split(",") if i != ""]
...: print(c)
...:
[1, 20, 300, 4000, 50000, 600000]


&>&>&> flatten = lambda l: loads( "[%s]" % (dumps(l).replace("[", "").replace("]", "")))
&>&>&> l
[1, ["2", 3]]
&>&>&> flatten(l)
[1, u"2", 3]

Obviously this doesn"t work if any of the strings contain [].


剛好前幾天自己寫了一個,最好使用yield from(是不是叫遞歸生成器?)

手機回答,自己看文檔,裡面有我的垃圾代碼

https://github.com/Zousiyu/code_snippet

論優雅,還是生成器優雅,而且在序列非常大的時候,生成器這種惰性序列是有絕對優勢的。

from collections import Iterable

def unfold(items, ignore_types=(str, bytes)):

for item in items:
if isinstance(item, Iterable) and not isinstance(item, ignore_types):
yield from unfold(item)
else:
yield item

如果序列的深度和大小很平常,不至於達到以百萬計的級別,遞歸實現也行

from collections import Iterable

def unfold(items, ignore_types=(str, bytes)):
unfolded = []
for item in items:
if isinstance(item, Iterable) and not isinstance(item, ignore_types):
unfolded.extend(unfold(item))
else:
unfolded.append(item)

return unfolded


np的reshape

很奇怪,我在這寫了個錯的也有人贊。


想問有沒有c++版本


import numpy as np

lst = np.hstack(lst).tolist()


額,難道不是序列解包??最快沒有之一


def lowest(List=list):
l=[]
def lower(List = list):
for i in List:
if isinstance(i,list):
lower(i)
else:
l.append(i)

lower(List)

return l


最近在做CS61a的題目時有遇到過,沒用yield,遞歸一下

def flatten(lst):
"""Returns a flattened version of lst.

&>&>&> flatten([1, 2, 3]) # normal list
[1, 2, 3]
&>&>&> x = [1, [2, 3], 4] # deep list
&>&>&> flatten(x)
[1, 2, 3, 4]
&>&>&> x = [[1, [1, 1]], 1, [1, 1]] # deep list
&>&>&> flatten(x)
[1, 1, 1, 1, 1, 1]
"""
if not lst:
return []
elif type(lst[0]) == list:
return flatten(lst[0]) + flatten(lst[1:])
else:
return [lst[0]] + flatten(lst[1:])


請自行使用二向箔


推薦閱讀:

請問用python3寫貪吃蛇時,怎麼只用左右兩個鍵控制蛇上下左右四個方向轉彎?
python 使用 threading.thread(target="")指明函數入口,如果函數有返回值,如何得到這個返回值?
Python 3.3 中 input() 返回值類型是什麼?
#Python3# Beautifulsoup Mac安裝解決辦法?[自問自答已解決]
linux上現在裝著python2.6,我想把python替換為python3.4,我應該怎麼做?

TAG:Python | Python3x | Python編程 |