這期內容當中小編將會給大家?guī)碛嘘P怎么將不規(guī)則的Python多維數(shù)組拉平到一維,文章內容豐富且以專業(yè)的角度為大家分析和敘述,閱讀完這篇文章希望大家可以有所收獲。
鞏留ssl適用于網(wǎng)站、小程序/APP、API接口等需要進行數(shù)據(jù)傳輸應用場景,ssl證書未來市場廣闊!成為創(chuàng)新互聯(lián)公司的ssl證書銷售渠道,可以享受市場價格4-6折優(yōu)惠!如果有意向歡迎電話聯(lián)系或者加微信:18982081108(備注:SSL證書合作)期待與您的合作!l = [[1, 2, 3], [4, 5, 6], [7, 8, 9]]
希望把它轉換成下面這種形式:
[1, 2, 3, 4, 5, 6, 7, 8, 9]
其實這個非常簡單,我將分享三個一行式代碼來解決這個問題。
但如果是下面這種不規(guī)則的多維列表:
l = [[1, 2], [3, 4], [5, [6, 7, [8, 9]]], 10, [11, [12, 13, [14, 15, [16]]]]]
我們想將它拉平到一維列表:
[1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16]
又該怎么實現(xiàn)呢?
文末將演示通過遞歸或棧來實現(xiàn)深度優(yōu)先遍歷策略從而解決這個問題。
import numpy as np np.array(l).flatten().tolist()
結果:
[1, 2, 3, 4, 5, 6, 7, 8, 9]
使用numpy數(shù)組拉平數(shù)組,其實很受限,一旦列表內部每個元素的長度不一致,numpy就不好使了:
l = [[1, 2, 3], [4, 5], [6, 7], [8, 9, 10, 11]] np.array(l).flatten().tolist()
D:\Anaconda3\lib\site-packages\ipykernel_launcher.py:2: VisibleDeprecationWarning: Creating an ndarray from ragged nested sequences (which is a list-or-tuple of lists-or-tuples-or ndarrays with different lengths or shapes) is deprecated. If you meant to do this, you must specify 'dtype=object' when creating the ndarray
結果:
[[1, 2, 3], [4, 5], [6, 7], [8, 9, 10, 11]]
這時我們可以通過python的itertools來實現(xiàn)高效的操作:
import itertools list(itertools.chain(*l))
結果:
[1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11]
當然還有一種更高級的操作方法是直接使用sum函數(shù):
sum(l, [])
結果:
[1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11]
你可能一臉懵逼,為什么sum函數(shù)可以實現(xiàn)列表的拉平?下面我翻譯一下,這段代碼實際做了什么:
result = [] for i in l: result += i result
結果:
[1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11]
例如,對于下面這個復雜的列表:
l = [[1, 2], [3, 4], [5, [6, 7, [8, 9]]], 10, [11, [12, 13, [14, 15, [16]]]]] l
結果:
[[1, 2], [3, 4], [5, [6, 7, [8, 9]]], 10, [11, [12, 13, [14, 15, [16]]]]]
這樣的列表,對于上面的方法來說已經都不好使了,這個時候怎么辦呢?
當然對于這種長度不長的列表,我們可以玩點小技巧:
list_str = str(l).replace("[", "").replace("]", "") eval(f"[{list_str}]")
結果:
[1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16]
當然,使用正則替換更佳:
import re eval(re.sub("(?!^)\[|\](?!$)", "", str(l)))
結果:
[1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16]
原理就是先將這個列表轉成普通的字符串,再將所有的[]字符都去掉,再轉成單維列表的字符串形式之后,用eval函數(shù)進行解析。但這種方式在列表足夠長的時候顯然是不合適的,會出現(xiàn)效率低下的問題。
下面我介紹一個正常的解決這個問題的辦法,那就是使用深度優(yōu)先遍歷策略來解決這個問題,當然如果你對拉平的結果沒有順序的要求還可以使用廣度優(yōu)先遍歷的策略。
深度優(yōu)先遍歷策略,最簡單直接的思路是使用遞歸來實現(xiàn):
def flatten(items, result=[]): for item in items: if isinstance(item, list): flatten(item, result) else: result.append(item) result = [] flatten(l, result) result
結果:
[1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16]
雖然遞歸可能出現(xiàn)調用棧過多導致性能下降或程序掛掉,但Python可以借助生成器讓遞歸調用變成普通調用:
def flatten(items): for item in items: if isinstance(item, list): yield from flatten(item) else: yield item result = [e for e in flatten(l)] result
結果:
[1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16]
而如果我們想不使用遞歸或生成器類遞歸,可以直接借助一個棧來實現(xiàn)。
為了保證結果是原有的順序,我們把左端作為棧頂,而數(shù)組不適合刪除左端的數(shù)據(jù),所以可以使用deque來作為棧。
首先,我們需要將原列表轉換為deque,下面是處理代碼:
from collections import deque stack = deque(l) result = [] while len(stack) != 0: item = stack.popleft() if isinstance(item, list): for e in reversed(item): stack.appendleft(e) else: result.append(item) result
結果:
[1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16]
如果我們將原列表作為一個右端為棧頂?shù)臈?,可以通過向結果左端插入數(shù)據(jù)來保持原有的順序:
from collections import deque stack = l.copy() result = deque() while len(stack) != 0: item = stack.pop() if isinstance(item, list): for e in item: stack.append(e) else: result.appendleft(item) result = list(result) result
結果:
[1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16]
上述就是小編為大家分享的怎么將不規(guī)則的Python多維數(shù)組拉平到一維了,如果剛好有類似的疑惑,不妨參照上述分析進行理解。如果想知道更多相關知識,歡迎關注創(chuàng)新互聯(lián)行業(yè)資訊頻道。