仅在满足条件的情况下,我才尝试从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}]}
我设法实现了最终目标,但是我认为可以肯定地将其改进。有帮助吗?
答案 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}]}