更新字典嵌套数组中的字典

update dictionary in nested array of dictionaries

提问人:Soma Juice 提问时间:11/17/2023 最后编辑:Soma Juice 更新时间:11/17/2023 访问量:48

问:

我想根据 opti 数组中的值更新 list2,以便它检查嵌套数组是否具有键为“RSI_15”的字典,然后使用同一数组中的键“val”更新字典,依此类推 opti 数组中的所有数组。

现在我的输出是这样的

[['random', {'ind': 'RSI_15'}, {'cond': '<'}, {'val': 1000}], ['random', {'ind': 'volume'}, {'cond': '>'}, {'val': 1000}]]

很明显,我的 for 循环覆盖了它,但我无法破解逻辑

我希望的输出是这样的:

[['random', {'ind': 'RSI_15'}, {'cond': '<'}, {'val': 15}], ['random', {'ind': 'volume'}, {'cond': '>'}, {'val': 1000}]]

法典:

list2 = [['random', {'ind': 'RSI_15'}, {'cond': '<'}, {'val': 12}], ['random', {'ind': 'volume'}, {'cond':
                                                                                               '>'}, {'val': 44}]]

opti = [['RSI_15', 15], ['volume', 1000]]

def update_val(indicator, val, values):
    flag = False
    for v in values:
        if isinstance(v, dict) and flag == False:
            try:
                v['ind'] = indicator
                flag = True
            except:
                continue
        if isinstance(v, dict) and flag == True:
            try:
                if v['val'] :
                    v['val'] = val
                    flag = True
            except:
                continue
        

def up(conds, opti_val):
    for cond in conds:
        for item in opti_val:
            update_val(item[0], item[1], cond)
    return conds



list2 = up(list2, opti)
print(list2)
Python 数组字

评论

1赞 Barmar 11/17/2023
v['ind'] == indicator什么都不做。它比较了指标,但它不是指标的一部分,所以什么也没发生。if
0赞 Soma Juice 11/17/2023
哦,是一个错别字,在最后一分钟偷偷溜进来,应该是 v['ind'] = 指标
0赞 Barmar 11/17/2023
为什么要改变?您只想搜索匹配的指标。v['ind']
0赞 alec_djinn 11/17/2023
子列表的顺序重要吗?我会得到相同的结果,像这样交换输入吗?opti = [['volume', 1000], ['RSI_15', 15]]
0赞 Soma Juice 11/17/2023
@alec_djinn的想法是应该给出相同的结果

答:

1赞 Barmar 11/17/2023 #1

我无法弄清楚你的逻辑应该如何工作,因为你在条件语句之外进行了比较。v['ind'] == indicator

但是,使用搜索列表的函数可以大大简化它,而不是使用令人困惑的变量进行循环。any()flag

def update_val(indicator, val, values):
    if any(isinstance(v, dict) and v.get('ind') == indicator for v in values):
        for v in values:
            if isinstance(v, dict) and 'val' in v:
                v['val'] = val;
                break

评论

0赞 Soma Juice 11/17/2023
噢:D噢非常感谢伙计!
0赞 Barmar 11/17/2023
是的,这是一个非常有用的功能。
0赞 Barmar 11/17/2023
您还应该考虑重新设计数据结构。列表通常应具有统一的数据,并且每个字典具有不同键的字典列表是反模式。为什么列表不像字典?{'type': 'random', 'ind': 'RSI_15', 'cond': <', 'val': 15}
0赞 Soma Juice 11/17/2023
是的,这是一个很好的观点,但恐怕必须是这种抽搐的方式
1赞 alec_djinn 11/17/2023 #2

你的方法过于复杂。您可以使用对特定数据结构进行操作的单个函数来完成所有操作。此外,最好不要修改输入,而是返回修改后的副本。虽然,这最终将是你的决定。 最后,您可以在断开循环时使用 for/else 来代替标记。

这是一个简单的实现

def update(input_data, input_calls):
    for _id, ind, cond, val in input_data:
        for call in input_calls:
            if ind['ind'] in call:
                yield [_id,
                       {'ind': ind['ind']},
                       {'cond': cond['cond']},
                       {'val': call[-1]} #here it updates the value
                      ]
                break
        else:
            yield row
 
input_data = [['random', {'ind': 'RSI_15'}, {'cond': '<'}, {'val': 12}], ['random', {'ind': 'volume'}, {'cond':'>'}, {'val': 44}]]
input_calls = [['ddd', 1000], ['volume', 1000], ['RSI_15', 15]] #testing odd calls

updated_data = list(update(input_data, input_calls))

print(updated_data)
#[['random', {'ind': 'RSI_15'}, {'cond': '<'}, {'val': 15}], ['random', {'ind': 'volume'}, {'cond': '>'}, {'val': 1000}]]
1赞 JustLearning 11/17/2023 #3

按照 for 循环的逻辑,这里有一个改进的方法:

for opt in opti:                                                                                                                      
    for sublist in list2:                                                                                                             
        indicator_detected = False                                                                                                    
        for elem in sublist:                                                                                                          
            if isinstance(elem, dict):                                                                                                
                if list(elem.values())[0] == opt[0]:                                                                                  
                    indicator_detected = True                                                                                         
                                                                                                                                      
        if indicator_detected:                                                                                                        
            for elem in sublist:                                                                                                      
                if isinstance(elem, dict):                                                                                            
                    if list(elem.keys())[0] == 'val':                                                                                 
                        elem['val'] = opt[1]

也就是说,检查每个子列表的一个元素是否是字典,以及该字典是否具有给定的键,可以像其他答案所示,使用和理解以不那么麻烦(可能更快)的方式编写。any