Python:根据键值条件从字典列表中删除元素

时间:2020-06-14 19:56:40

标签: python list dictionary

仅在满足条件的情况下,我才尝试从dict中删除元素。

例如,

dd = {'11': [{'xx': 259, 'yy': 1, 'channels': 55}, {'xx': 260, 'yy': 2, 'channels': 35}], '22': [{'xx': 259, 'yy': 1, 'channels': 40}, {'xx': 303, 'yy': 2, 'channels': 30}]}

场景:

channels = 60

在上面的嵌套字典中,有两个元素的键为xx = 259,我希望仅保留一个更接近channels = 60值的元素。

预期输出:

dd = {'11': [{'xx': 259, 'yy': 1, 'channels': 55}, {'xx': 260, 'yy': 2, 'channels': 35}], '22': [{'xx': 303, 'yy': 2, 'channels': 30}]}

我到目前为止尝试过:

channels = 60
for key, values in dd.items():
    key = str(key)
    if key in dd:
        for elem in dd[key]:
            if elem['xx'] == 259:
                print(elem)
                # some logic here to check the closest value to channels and remove the furthest one

哪个输出:

{'xx': 259, 'yy': 1, 'channels': 55}
{'xx': 259, 'yy': 1, 'channels': 40}

更新方法:

    channels = 60
    xList = []
    for key, values in dd.items():
        key = str(key)
        if key in dd:
            for elem in dd[key]:
                if elem['xx'] == 259:
                    xList.append(elem['channels'])


    result =min(xList, key=lambda x: abs(x - 60))

    # find and remove elem from dict
    for key, values in dd.items():
        key = str(key)
        if key in dd:
            for elem in dd[key]:
                if elem['xx'] == 259:
                    if elem['channels'] == result:
                        pass
                    else:
                        print("delete this elem: ", elem)
                        dd[key].remove(elem)
    print(dd)

输出:

{'11': [{'xx': 259, 'yy': 1, 'channels': 55}, {'xx': 260, 'yy': 2, 'channels': 35}], '22': [{'xx': 303, 'yy': 2, 'channels': 30}]}

我设法实现了最终目标,但是我认为可以肯定地将其改进。有帮助吗?

2 个答案:

答案 0 :(得分:1)

我认为这可以满足您的需求,而无需搜索 匹配第二个循环中的项目(remove()必须这样做) 所有候选元素的键和索引,然后删除所有 但其delta值最低。

channels = 60
xList = []
for key, values in dd.items():
    for index,elem in enumerate(values):
        if elem['xx'] == 259:
            xList.append((abs(elem['channels']-channels),key,index)) # capture delta, key, and index

# this drops the lowest difference entry and sorts the remaining (deletions) in reverse index order
xList=sorted([(key,index) for (delta,key,index) in sorted(xList)[1:]],reverse=True)

# the deletions must be done from highest index to lowest index
for key,index in xList:  # pull indexes from highest to lowest
    del dd[key][index]

print(dd)

(编辑:以上代码的早期版本括号位置错误)

此版本将删除每个键中除最接近的以外的所有,而不是全部:

channels = 60
for key, values in dd.items():
    xList = []
    for index,elem in enumerate(values):
        if elem['xx'] == 259:
            xList.append((abs(elem['channels']-channels),index)) # capture delta and index
    # this drops the lowest difference entry and sorts the remaining (deletions) in reverse index order
    xList=sorted([index for (delta,index) in sorted(xList)[1:]],reverse=True)
    for index in xList:  # pull indexes from highest to lowest
        del dd[key][index]

(我将处理放入循环中,并从选择列表中删除了键)

答案 1 :(得分:0)

我发现一种解决方案比到目前为止的解决方案更为紧凑。代码本身不是清晰的示例,但它的运行速度相当快。我还扩展了您的示例词典,因此我们可以测试键259为多个子词典的情况。

from collections import defaultdict

CHANNELS = 60

dd = {'11': [{'xx': 259, 'yy': 1, 'channels': 55},
             {'xx': 259, 'yy': 2, 'channels': 30},
             {'xx': 260, 'yy': 3, 'channels': 35}],
      '22': [{'xx': 259, 'yy': 1, 'channels': 40},
             {'xx': 259, 'yy': 2, 'channels': 45},
             {'xx': 303, 'yy': 3, 'channels': 30}]}


# Nasty list comprehension to get the items where 'xx' == 259

ddlst = [[key, idx, valin['channels']] for key, val in dd.items()
         for idx, valin in enumerate(val) if valin['xx'] == 259]

ddlstkey = defaultdict(list)
for key, *vals in ddlst:
    ddlstkey[key].append(vals)
ddlstkey = dict(ddlstkey)

# Delete from the previous list the element that is closer to channels = 60

for k, i in ddlstkey.items():
    minval = min(ddlstkey[k], key=lambda x: abs(x[:][1] - CHANNELS))
    ddlstkey[k].remove(minval)

# Finally delete the non-minimum items from original dictionary

for key, vals in ddlstkey.items():
    for vl in reversed(vals):
        del dd[key][vl[0]]

print(dd)

这将输出:

{'11': [{'xx': 259, 'yy': 1, 'channels': 55}, {'xx': 260, 'yy': 3, 'channels': 35}], '22': [{'xx': 259, 'yy': 2, 'channels': 45}, {'xx': 303, 'yy': 3, 'channels': 30}]}