我从JSON格式的API批量接收数据。我希望只在列表中存储值。
原始数据看起来像,并且总是如下所示,即:所有{...}看起来像第一个例子:
data = content.get('data')
>>> [{'a':1, 'b':{'c':2, 'd':3}, 'e':4}, {...}, {...}, ...]
嵌套字典使这更难;我也需要打开包装。
这就是我所拥有的,但它感觉非常糟糕:
unpacked = []
data = content.get('data')
for d in data:
item = []
for k, v in d.items():
if k == 'b':
for val in v.values():
item.append(val)
else:
item.append(v)
unpacked.append(item)
输出:
>>> [[1,2,3,4], [...], [...], ...]
我该如何改善这个?
答案 0 :(得分:3)
您可以使用递归函数和某些类型测试:
data = [{'a':1, 'b':{'c':2, 'd':3}, 'e':4}, {'f':5,'g':6}]
def extract_nested_values(it):
if isinstance(it, list):
for sub_it in it:
yield from extract_nested_values(sub_it)
elif isinstance(it, dict):
for value in it.values():
yield from extract_nested_values(value)
else:
yield it
print(list(extract_nested_values(data)))
# [1, 2, 3, 4, 5, 6]
请注意,它会输出一个平面生成器,而不是列表列表。
答案 1 :(得分:2)
假设您的词典不包含内部列表,您可以定义一个简单的例程来解压缩嵌套字典,并使用循环遍历数据中的每个项目。
def unpack(data):
for k, v in data.items():
if isinstance(v, dict):
yield from unpack(v)
else:
yield v
请注意,由于yield from
的魔力,此功能非常简单。现在,让我们用一些数据来称呼它。
data = [{'a':1, 'b':{'c':2, 'd':3}, 'e':4}, {'f':5,'g':6}] # Data "borrowed" from Kaushik NP
result = [list(unpack(x)) for x in data]
print(result)
[[2, 3, 1, 4], [5, 6]]
请注意结果中缺少顺序,因为字典的任意顺序。
答案 2 :(得分:1)
出于完整性考虑,基于埃里克·杜米尼尔(Eric Duminil)的出色回答,以下函数可返回嵌套字典或列表的最大深度:
def depth(it, count=0):
"""Depth of a nested dict.
# Arguments
it: a nested dict or list.
count: a constant value used in internal calculations.
# Returns
Numeric value.
"""
if isinstance(it, list):
if any(isinstance(v, list) or isinstance(v, dict) for v in it):
for v in it:
if isinstance(v, list) or isinstance(v, dict):
return depth(v, count + 1)
else:
return count
elif isinstance(it, dict):
if any(isinstance(v, list) or isinstance(v, dict) for v in it.values()):
for v in it.values():
if isinstance(v, list) or isinstance(v, dict):
return depth(v, count + 1)
else:
return count
else:
return count
在Python传统中,它是从零开始的。
答案 3 :(得分:0)
递归地执行:
def traverse(d):
for key,val in d.items():
if isinstance(val, dict):
traverse(val)
else:
l.append(val)
out=[]
for d in data:
l=[]
traverse(d)
out.append(l)
print(out)
#driver values:
IN : data = [{'a':1, 'b':{'c':2, 'd':3}, 'e':4}, {'f':5,'g':6}]
OUT : out = [[1, 2, 3, 4], [5, 6]]
编辑:更好的方法是使用yield
,以便不必像第一种方法那样依赖全局变量。
def traverse(d):
for key,val in d.items():
if isinstance(val, dict):
yield from traverse(val)
else:
yield val
out = [list(traverse(d)) for d in data]
答案 4 :(得分:0)
其他答案(特别是@COLDSPEED)已经涵盖了这种情况,但是这里有一个略有不同的代码,基于旧格言最好是请求宽恕而非许可,我倾向于选择检查:
def unpack(data):
try:
for value in data.values():
yield from unpack(value)
except AttributeError:
yield data
data = [{'a':1, 'b':{'c':2, 'd':3}, 'e':4}]
unpacked = [list(unpack(item)) for item in data]