字典相互嵌套去除指定字段指定部分的全部数据

问题遇到的现象和发生背景

想要将seq:7后面的iboy里的scd:9,scd:7取出来该怎么做

尝试过的解决方法
[{abc:1212,iheader:[  {seq:7,iboy:[{scd:9},{scd:7}],seq:8,iboy:[{scd:8},{sdf:4}]     }            ]               }]


首先,你这个数据结构叫人眼花缭乱。其中有一些错误:在同一字典中,关键字不重复。(第二层花括号seq, iboy是重复的)
其次,不知道你这个数据结构是固定不变的(普遍的情况),还是仅为举例说明嵌套的层次多(特例的情况)。
针对不同的情况,有不同的解决方法。

方法一: 不改变数据结构

就以你这个例子来说明,如何访问到每一个元素。(嵌套以固定的格式)
为了方便,改正了关键字重复的错误。另外,对关键字变量进行了模拟赋值。(因你程序不完整)

我不知道,你这个 sdf 是不是 scd 的笔误。姑且原样照抄吧。

# 原题:[{abc: 1212, iheader: [{seq: 7, iboy: [{scd: 9}, {scd: 7}], seq: 8, iboy: [{scd: 8}, {sdf: 4}]}]}]
# 模拟变量,方便输出:
abc, iheader, seq7, iboy7, scd9, scd7, seq8, iboy8, scd8, sdf, scd = ('abc', 'iheader', 'seq7', 'iboy7', 'scd9', 'scd7', 'seq8', 'iboy8', 'scd8', 'sdf', 'scd')
li = [{abc: 1212, iheader: [{seq7: 7,
                             iboy7: [{scd: 9}, {scd: 7}],
                             seq8: 8,
                             iboy8: [{scd: 8}, {sdf: 4}]
                             }
                            ]
       }
      ]

print(li)
print(f'abc = {li[0][abc]}')
print(f'iheader = {li[0][iheader]}')
print(f'seq7 = {li[0][iheader][0][seq7]}')
print(f'iboy7 = {li[0][iheader][0][iboy7]}')
print(f'scd9 = {li[0][iheader][0][iboy7][0][scd]}')
print(f'scd7 = {li[0][iheader][0][iboy7][1][scd]}')
print(f'seq8 = {li[0][iheader][0][seq8]}')
print(f'iboy8 = {li[0][iheader][0][iboy8]}')
print(f'scd8 = {li[0][iheader][0][iboy8][0][scd]}')
print(f'sdf = {li[0][iheader][0][iboy8][1][sdf]}')

以下是程序运行结果:

# [{'abc': 1212, 'iheader': [{'seq7': 7, 'iboy7': [{'scd': 9}, {'scd': 7}], 'seq8': 8, 'iboy8': [{'scd': 8}, {'sdf': 4}]}]}]
# abc = 1212
# iheader = [{'seq7': 7, 'iboy7': [{'scd': 9}, {'scd': 7}], 'seq8': 8, 'iboy8': [{'scd': 8}, {'sdf': 4}]}]
# seq7 = 7
# iboy7 = [{'scd': 9}, {'scd': 7}]
# scd9 = 9
# scd7 = 7
# seq8 = 8
# iboy8 = [{'scd': 8}, {'sdf': 4}]
# scd8 = 8
# sdf = 4

方法二,修改数据结构,主要是采取 namedtuple 来嵌套。

当然了,方法有很多种。

scd, sdf = 'scd', 'sdf'
iboy = namedtuple('iboy', ['scd1', 'scd2'])
iheader = namedtuple('iheader', ['seq', 'iboy'])
data = namedtuple('data', ['abc', 'iheader'])
iboy7 = iboy(scd1={scd: 9}, scd2={scd: 7})
iboy8 = iboy(scd1={scd: 8}, scd2={sdf: 4})
iheader7 = iheader(seq=7, iboy=iboy7)
iheader8 = iheader(seq=8, iboy=iboy8)
data1 = data(abc=1212, iheader=[iheader7, iheader8])
li = [data1]
print(li)
print(li[0].abc)
print(li[0].iheader)
print(li[0].iheader[0].seq)
print(li[0].iheader[1].iboy)
print(li[0].iheader[1].iboy.scd2[sdf])

运行结果如下(举例只是列举了一部分):

# [data(abc=1212, iheader=[iheader(seq=7, iboy=iboy(scd1={'scd': 9}, scd2={'scd': 7})), iheader(seq=8, iboy=iboy(scd1={'scd': 8}, scd2={'sdf': 4}))])]
# 1212
# [iheader(seq=7, iboy=iboy(scd1={'scd': 9}, scd2={'scd': 7})), iheader(seq=8, iboy=iboy(scd1={'scd': 8}, scd2={'sdf': 4}))]
# 7
# iboy(scd1={'scd': 8}, scd2={'sdf': 4})

方法三:数据结构是动态的

假如不知列表或字典嵌套了几层,可以用递归函数。
这里,关键字的命名很重要,否则你也不知道取的是第几层的什么变量。

基本搞清楚了你的需求,写了一个相对完整的代码,从网页抓取、到数据解析,直到数据保存。

import requests
import csv
url = '...'     # 这里替换成你的网址
head = {...}    # 这里替换成你的请示头
res = requests.get(url=url, headers=head).json()    # 确定网页发送的是json数据。

# 预定义字段
data_keys = ['AllocatedID','SortSeq','cInvCode','cInvStd','cComUnitName','BaseQtyN','BaseQtyD','iQuantity','cSRPolicy','iPlanDefault']
# 一行数据的值:11个字段
Vars = []
# 读取数据,这里替换成 json 对象的名称。
lis = res['result']
# 保存数据的文件
with open('保存数据.csv', encoding='utf-8', mode='a', newline='') as f:
    csv_w = csv.writer(f)
# 解析数据
for dic in lis:
    for iHeader in dic.keys():
        li_iHeaders = dic['iHeader']
        for Seq_dic in li_iHeaders:
            li_iBody = Seq_dic['iBody']
            for data_dict in li_iBody:
                for i in range(len(data_keys)):
                    Vars[i] = data_dict[data_keys[i]]
                    csv_w.writerow(Vars)
f.close()

说明如下:

  • 循环的层次有点多,这是假设你的每层数据都有展开的情况。
    必要时,外层循环可以拿掉,例如:第一层, dic = lis[0]
  • 不知你的数据库类型,所以写在 csv 里了,可以直接用 Excel 打开,检查数据读取是否正确、完整。

    Alt


    本答复由 大侠(AhcaoZhu)原创,转载请声明。
    链接: https://blog.csdn.net/Ahcao2008

你的属性名全是些变量呀

如果你的这个字符串就是这种样式的话,那不好处理

针对该问题,可以使用 Python 中的列表和字典嵌套来实现。

首先,需要明确的是,给定的数据是一个列表,该列表包含一个字典,该字典包含两个键值对:abc 和 iheader。iheader 的值是一个列表,该列表包含一个字典,该字典包含两个键值对:seq 和 iboy。iboy 的值是一个列表,包含两个字典,每个字典都包含一个键值对:scd。

因此,要取出 seq 为 7 后面的 iboy 中的 scd 为 9 和 7 的字典,可以按照以下步骤进行:

  • 遍历给定数据的列表,取出字典。
  • 从字典中取出 iheader 对应的值,得到一个包含一个字典的列表。
    从该字典中取出 seq 对应的值,判断是否为 7,如果不是,则跳过该字典。
    如果 seq 为 7,则从该字典中取出 iboy 对应的值,得到一个包含两个字典的列表。
    遍历该列表,取出字典。
    从字典中取出 scd 对应的值,判断是否为 9 或 7,如果是,则将该字典取出并存入一个新的列表中。
    最终,得到的新列表即为包含满足条件的字典的列表。

下面是一个示例代码,可以实现上述步骤:

data = [{'abc': 1212, 'iheader': [{'seq': 7, 'iboy': [{'scd': 9}, {'scd': 7}]}, {'seq': 8, 'iboy': [{'scd': 8}, {'sdf': 4}]}]}]

result = []

for item in data:
    header_list = item['iheader']
    for header in header_list:
        if header['seq'] == 7:
            iboy_list = header['iboy']
            for iboy in iboy_list:
                if iboy['scd'] in [9, 7]:
                    result.append(iboy)

print(result)

该代码会输出一个包含满足条件的字典的列表,即:

[{'scd': 9}, {'scd': 7}]

这些字典就是 iboy 中 scd 为 9 和 7 的部分数据。