Python 是否有一种方法可以从嵌套的dict中访问值,并基于搜索列表更新同一dict中的值?

Python 是否有一种方法可以从嵌套的dict中访问值,并基于搜索列表更新同一dict中的值?,python,python-3.7,Python,Python 3.7,我的目标是搜索一个_列表,找到以203和2042031111和2042222开头的第一个整数,并更新相应的soft_DN值 更新的dict应如下所示: dict_1 = {'key1': {'Type': '51', 'dn_range': 203, 'soft_DN': nan}} {'key2': {'Type': '51', 'dn_range': 204, 'soft_DN': nan}} A_list = [2031111, 2031112, 2031113, 2042222, 20

我的目标是搜索一个_列表,找到以203和2042031111和2042222开头的第一个整数,并更新相应的soft_DN值

更新的dict应如下所示:

dict_1 = {'key1': {'Type': '51', 'dn_range': 203, 'soft_DN': nan}}
{'key2': {'Type': '51', 'dn_range': 204, 'soft_DN': nan}}

A_list = [2031111, 2031112, 2031113, 2042222, 2042223]
for key, entry in dict_1.items():
    dn_range = entry["dn_range"]
    for dn in A_list:
        if dn_range * 10000 <= dn < dn_range + 1 * 10000:
            entry["soft_DN"] = dn
            break

下面的代码将按照您的意愿工作:

dict_1 = {'key1': {'Type': '51', 'dn_range': 203, 'soft_DN': 2031111}}
{'key2': {'Type': '51', 'dn_range': 204, 'soft_DN': 2042222}}
首先,我把这两本词典分为dict_1和dict_2。 然后在for循环的前三行中,我去掉了数字中不必要的部分,因为我们只想检查前三位数字 然后我检查键“dn_range”。如果数字与之匹配,则将-1重写为第一个正确的数字。
假设列表中的第一个整数。。。表示第一个索引,而不是最小的索引,如果列表未排序,则您可以在字典中循环并在A_列表中搜索dict中的每个条目:

dict_1 = {'key1': {'Type': '51', 'dn_range': 203, 'soft_DN': -1}} 
dict_2 = {'key2': {'Type': '51', 'dn_range': 204, 'soft_DN': -1}}

A_list = [2031111, 2031112, 2031113, 2042222, 2042223]

for i, x in enumerate(A_list):
    #Get rid of unnecessary part
    x = str(x)
    x = x[:3]
    x = int(x)

    if x == dict_1["key1"]["dn_range"] and dict_1["key1"]["soft_DN"] == -1:
        dict_1["key1"]["soft_DN"] = A_list[i]    
    
    if x == dict_2["key2"]["dn_range"] and dict_2["key2"]["soft_DN"] == -1:
        dict_2["key2"]["soft_DN"] = A_list[i]

print(dict_1, dict_2)

如果对_列表进行了排序,则可以进行二进制搜索以查找目标dn值,而不是逐个查看列表。这将大大加快您的算法。

首先,您的dict格式不正确,我想应该是这样的:

dict_1 = {'key1': {'Type': '51', 'dn_range': 203, 'soft_DN': nan}}
{'key2': {'Type': '51', 'dn_range': 204, 'soft_DN': nan}}

A_list = [2031111, 2031112, 2031113, 2042222, 2042223]
for key, entry in dict_1.items():
    dn_range = entry["dn_range"]
    for dn in A_list:
        if dn_range * 10000 <= dn < dn_range + 1 * 10000:
            entry["soft_DN"] = dn
            break
实现这一点的简单方法是将数字转换为字符串,然后将前3个字符与dn_范围进行比较

也就是说,我不知道您的数据集有多大,如果它相当大,您希望通过减少迭代dict时循环列表的次数来节省时间。为此,我建议使用itertools.groupby获得一个dict,其中键是整数的前3位数字,值是显示的第一个整数。也就是说,请确保您的整数按前3个字符分组,否则您将需要另一种方法来完成此操作

>>> int(str(2031111)[:3])
203
结果:

from itertools import groupby
ranges = {int(k): next(v) for k, v in groupby(A_list, key=lambda i: str(i)[:3])}
for k, d in dict_1.items():
    d['soft_DN'] = ranges.get(d['dn_range'])
然后循环遍历dict并替换这些值

{203: 2031111, 204: 2042222}
结果:

from itertools import groupby
ranges = {int(k): next(v) for k, v in groupby(A_list, key=lambda i: str(i)[:3])}
for k, d in dict_1.items():
    d['soft_DN'] = ranges.get(d['dn_range'])

我想Python中没有魔法。我只想:

迭代dict_1的条目,并针对每个条目: 获取dn_范围字段 迭代_列表中的项目,并针对每个项目: 检查项目是否以dn_范围字符串表示形式开头。此处字符串有startsWith方法,如果有: 更新dict条目并中断列表迭代循环。 Python循环非常类似于伪代码循环,易于编写和读取。你会喜欢他们的! 提示:

对于键,dict_1.项中的值: 对于列表中的项目: 如果strmy_item.startsWithstrd_范围:
足够的提示,快乐的编码

如果答案对你有帮助,请竖起大拇指我喜欢这个解决方案。为了确保列表中的整数分组在一起,您可以在创建范围之前对列表进行排序。@NanoTellez我想到了这一点,尽管排序可能会影响OP希望列表排序/排列的方式,从而可能会影响/更改第一个值。这实际上对我很有效,除了我忘了提到dict值可以复制外。。例如,'key2':{'Type':'51','dn_range':204,'soft_dn':None'key7':{'Type':'51',dn_range':204,'soft_dn':无在这种情况下,我想将列表中的第一个可用项分配给键1,因此2042222-和键7应该分配给列表中的下一个可用项204。感谢您的帮助help@NanoTellez等等,谢谢你的反馈!我使用了每个片段,并在转换为dict之前对数据帧进行排序+调用列表上的iter函数。我最终得到:A_list=iterA_list for key,dict_1中的值。items:A_list中的项:if stritem.startswithstrvalue['dn_range']:value['soft_dn']=item breakUsing dict.items将获得键、值对。然后,您可以使用for循环搜索和更新它们。