最近在接觸一些AI自動化的項目,發(fā)現(xiàn)幾乎所有的傳感器數(shù)據(jù)為了匹配API接口宫静,數(shù)據(jù)格式都是JSON。這個對與常年幾乎只用Data Frame的人來說一開始會很不習慣,稍微了解了一下python的遞歸函數(shù)摊鸡,發(fā)現(xiàn)用遞歸函數(shù)可以方便好多。
本文會分4步講解如何實現(xiàn)這個操作蚕冬。
Step.1 最簡單的遞歸函數(shù)
sample = ["a", "b", 1]
res = []
for v in sample:
if isinstance(v, str):
res.append(v)
print(res) # ["a", "b"]
尋找str構(gòu)造的數(shù)據(jù)免猾。
step.1純屬為了比較,無需多解釋囤热。
Step.2 雙層數(shù)據(jù)結(jié)構(gòu)的遞歸函數(shù)
sample = [["a", 1], "b"]
res = []
for arg in sample:
if isinstance(arg, str):
res.append(arg)
if isinstance(arg, list):
for v in arg:
if isinstance(v, str):
res.append(v)
print(res)
step.2的話相當于把step.1拆分成了兩步猎提。雖然得到了預(yù)期的結(jié)果,但是用到了兩次if條件旁蔼,使得整個代碼變得有點冗長锨苏。如果需要有更多步驟的話疙教,會產(chǎn)生更多的for循環(huán)和if條件分叉,代碼會變得更加冗長伞租。 所以需要遞歸函數(shù)松逊。遞歸函數(shù)的宗旨就是把大事化小,把復(fù)雜的項目分割成簡單的小塊肯夏。在接下來的step.3里會用到遞歸函數(shù)把step.2簡單化经宏。
Step.3 從n層構(gòu)造序列里獲取str數(shù)據(jù)
sample = ["a",["b", 1, [[["c", 2], 3], 4], "d"], ["e"]]
想要預(yù)期得到的結(jié)果如下
["a", "b", "c", "d", "e"]
def get_str(arg):
res = []
if isinstance(arg,str):
res.append(arg)
elif isinstance(arg,list):
for v in arg:
res += get_str(v)
return res
print(get_str(sample))
整個函數(shù)的運行從下往上看,首先運行的是
for v in arg:
res += get_str(v)
當然此處的arg有三種情況驯击,分別是
①res += get_str("a")
②res += get_str(["b", 1, [[["c", 2], 3], 4], "d"])
③res += get_str(["e"])
根據(jù)條件設(shè)定烁兰,每種情況的處理如下
①res += get_str("a")
情況1的話直接把結(jié)果添加到res里,到此結(jié)束
情況2的處理如下
②res += get_str(["b", 1, [[["c", 2], 3], 4], "d"])
res += get_str("b")
res += get_str(1)
res += get_str([[["c", 2], 3], 4])
res += get_str("d")
可以看到處理的并不完整徊都,會繼續(xù)處理沪斟。
情況3的處理如下
③res += get_str(["e"])
res += get_str("e")
完整的內(nèi)部操作如下:
①res += get_str("a")
>> res.append("a") *
②res += get_str(["b", 1, [[["c", 2], 3], 4], "d"])
>> res += get_str("b")
>> res.append("b") *
res += get_str(1)
res += get_str([[["c", 2], 3], 4])
>> res += get_str([["c", 2], 3)
>> res += get_str(["c", 2])
>> res += get_str("c")
>> res.append("c") *
res += get_str(2)
res += get_str(4)
res += get_str("d")
>> res.append("d") *
③res += get_str(["e"])
>> res += get_str("e")
>> res.append("e") *
其中帶*的結(jié)果會最終添加(return)到res里。用這樣的辦法就實現(xiàn)了使用get_str()函數(shù)在復(fù)雜的數(shù)據(jù)中尋找并添加str類型數(shù)據(jù)暇矫。和n個for循環(huán)比起來代碼更加簡潔明了主之。
Step.4 探索JSON
在復(fù)雜的JSON數(shù)據(jù)里尋找指定數(shù)據(jù)。假設(shè)在下面的例子里找到x,y,z
sample = {
"a": [{
"b": "y",
"c": [{
"d": [2,3]
}],
"e": {"g": "z"}
}],
"f": ["x"],
}
def get_str(arg):
res =[]
if isinstance(arg, str):
res.append(arg)
elif isinstance(arg, list):
for item in arg:
res += get_str(item)
elif isinstance(arg, dict):
for value in arg.values():
res += get_str(value)
return res
print(get_str(sample)) # ["x", "y", "z"]
原理是一樣的李根,無非就是和step3相比多了一個dict層槽奕。