
本教程旨在详细讲解如何在python中处理复杂的深度嵌套字典和列表数据结构。我们将通过一个实际案例,演示如何有效地遍历多层数据,提取特定字段(如`asset`、`free`、`locked`),并应用条件过滤(例如,排除`free`和`locked`字段均为'0'的条目),最终构建出符合需求的结果集。
在现代数据处理中,我们经常会遇到来自API响应、配置文件或日志等来源的复杂数据结构,它们通常以JSON格式呈现,并在Python中表现为嵌套的字典和列表。有效地从这些结构中提取所需信息并进行过滤,是数据处理的核心技能之一。
假设我们有以下Python字典数据,其中包含多层嵌套的列表和字典:
repo = {
'code': 200,
'msg': '',
'snapshotVos': [
{
'data': {
'balances': [
{'asset': 'ADD', 'free': '10', 'locked': '0'},
{'asset': 'RDP', 'free': '0', 'locked': '0'},
{'asset': 'SHIB', 'free': '0', 'locked': '947415'}
],
'totalAsset': '152'
},
'type': 'spot',
'updateTime': 1703807999000
}
]
}这个repo字典的结构如下:
我们的目标是从上述repo字典中提取balances列表中的所有条目,但需要满足以下两个条件:
立即学习“Python免费学习笔记(深入)”;
最终结果应是一个列表,其中包含符合条件的资产余额信息。
为了实现上述目标,我们需要逐层深入数据结构,并应用适当的循环和条件判断。
首先,我们需要访问repo字典中的snapshotVos键,它是一个列表。由于这个列表可能包含多个元素(尽管我们的示例中只有一个),我们需要一个循环来遍历它。
rows1 = [] # 用于存储最终结果的列表
for item in repo['snapshotVos']:
# 在这里处理每个item
pass在snapshotVos列表的每个item中,我们感兴趣的数据位于item['data']['balances']。balances本身又是一个列表,其中包含多个资产字典。
rows1 = []
for item in repo['snapshotVos']:
data_content = item['data']
balances_list = data_content['balances']
# 现在,balances_list 是一个包含资产字典的列表
pass现在我们有了balances_list,我们需要再次使用循环来遍历其中的每一个资产字典(我们称之为balance)。在每次迭代中,我们将应用过滤条件。
rows1 = []
for item in repo['snapshotVos']:
for balance in item['data']['balances']:
# 检查过滤条件:如果 'free' 和 'locked' 字段不都为 '0'
if not (balance['free'] == '0' and balance['locked'] == '0'):
# 提取所需的值
# 原始问题要求“获取键从 'asset', 'free', 'locked'”,
# 答案提供的是这些键的值列表。
# 如果需要的是值列表:
val = [balance['asset'], balance['free'], balance['locked']]
# 如果需要的是一个包含这些键值对的字典:
# val = {'asset': balance['asset'], 'free': balance['free'], 'locked': balance['locked']}
# 确保不添加重复的条目 (如果需要去重)
if val not in rows1:
rows1.append(val)关于去重说明: 原始答案中的if val not in rows1: 是为了确保最终结果列表中不包含重复的条目。如果数据源本身保证不重复,或者允许重复,则可以省略此检查以提高效率。
将上述步骤整合,得到完整的解决方案代码:
repo = {
'code': 200,
'msg': '',
'snapshotVos': [
{
'data': {
'balances': [
{'asset': 'ADD', 'free': '10', 'locked': '0'},
{'asset': 'RDP', 'free': '0', 'locked': '0'},
{'asset': 'SHIB', 'free': '0', 'locked': '947415'}
],
'totalAsset': '152'
},
'type': 'spot',
'updateTime': 1703807999000
},
# 假设 snapshotVos 中可能有更多元素,或者 balances 中有重复项
{
'data': {
'balances': [
{'asset': 'ADD', 'free': '10', 'locked': '0'}, # 这是一个重复项
{'asset': 'BTC', 'free': '0.5', 'locked': '0.1'}
],
'totalAsset': '200'
},
'type': 'margin',
'updateTime': 1703808000000
}
]
}
rows1 = [] # 用于存储最终结果的列表
for item in repo['snapshotVos']:
for balance in item['data']['balances']:
# 检查过滤条件:如果 'free' 和 'locked' 字段不都为 '0'
if not (balance['free'] == '0' and balance['locked'] == '0'):
# 提取 'asset', 'free', 'locked' 的值作为一个列表
# 如果你希望得到一个字典,可以改为:
# val = {'asset': balance['asset'], 'free': balance['free'], 'locked': balance['locked']}
val = [balance['asset'], balance['free'], balance['locked']]
# 检查是否已存在,避免重复添加
if val not in rows1:
rows1.append(val)
print(rows1)运行上述代码,将得到如下输出:
[['ADD', '10', '0'], ['SHIB', '0', '947415'], ['BTC', '0.5', '0.1']]
从输出中可以看到:
在实际数据中,字典的键可能不是每次都存在。为了避免KeyError,可以使用字典的get()方法提供默认值,或者使用try-except块。
# 使用 .get() 方法
asset = balance.get('asset', 'N/A')
free = balance.get('free', '0') # 如果键不存在,默认为 '0'
locked = balance.get('locked', '0')如果希望结果列表中的每个元素是一个字典,而不是值的列表,可以修改val的构建方式:
# ... (循环部分相同)
if not (balance.get('free', '0') == '0' and balance.get('locked', '0') == '0'):
val = {
'asset': balance.get('asset'),
'free': balance.get('free'),
'locked': balance.get('locked')
}
if val not in rows1: # 注意:字典的去重比较复杂,可能需要自定义逻辑
rows1.append(val)如果返回字典,if val not in rows1: 的去重逻辑可能需要更精细的实现,因为字典的相等性比较是基于键值对的。
对于这种提取和过滤操作,Python的列表推导式(List Comprehension)可以使代码更简洁、更具可读性:
rows1_comprehension = [
[balance['asset'], balance['free'], balance['locked']]
for item in repo['snapshotVos']
for balance in item['data']['balances']
if not (balance['free'] == '0' and balance['locked'] == '0')
]
# 注意:列表推导式默认不会去重。如果需要去重,可以转换为set再转回list,
# 或者使用更复杂的推导式结合set。
# 例如,如果需要去重并保持顺序,可以这样做:
seen = set()
unique_rows1 = []
for row in rows1_comprehension:
if tuple(row) not in seen: # 列表不能直接放入set,需要转换为不可变的tuple
seen.add(tuple(row))
unique_rows1.append(row)
print(unique_rows1)请注意,示例数据中的free和locked值是字符串(例如'10'、'0')。如果需要进行数值比较或计算,务必将其转换为整数或浮点数。
# 过滤条件可以改为数值比较
# if not (int(balance.get('free', '0')) == 0 and int(balance.get('locked', '0')) == 0):在进行类型转换前,务必确保字符串可以安全地转换为数字,否则可能引发ValueError。
从嵌套的Python字典和列表中提取和过滤数据是日常编程中的常见任务。通过理解数据结构、运用嵌套循环和条件判断,我们可以精确地定位并处理所需的数据。列表推导式提供了一种更Pythonic、更简洁的解决方案。在实际应用中,还需考虑键的缺失、数据类型转换以及去重等问题,以确保代码的健壮性和准确性。
以上就是Python中深度嵌套字典与列表的数据提取与条件过滤指南的详细内容,更多请关注php中文网其它相关文章!
每个人都需要一台速度更快、更稳定的 PC。随着时间的推移,垃圾文件、旧注册表数据和不必要的后台进程会占用资源并降低性能。幸运的是,许多工具可以让 Windows 保持平稳运行。
Copyright 2014-2025 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号