2

Python dict 键删除,如果键模式与其他 dict 键匹配。

例如

a={'a.b.c.test':1,  'b.x.d.pqr':2,  'c.e.f.dummy':3,  'd.x.y.temp':4}

b={'a.b.c':1,  'b.p.q':20}

结果

a={'b.x.d.pqr':2,'c.e.f.dummy':3,'d.x.y.temp':4}`  
4

3 回答 3

4

如果“pattern match with other dict key”的意思是“从另一个 dict 中的任何键开始”,那么最直接的写法是这样的:

a = {k:v for (k, v) in a.items() if any(k.startswith(k2) for k2 in b)}

如果乍一看很难理解,它基本上相当于:

def matches(key1, d2):
    for key2 in d2:
        if key1.startswith(key2):
            return True
    return False

c = {}
for key in a:
  if not matches(key, b):
    c[key] = a[key]
a = c

这将比必要的慢。如果a有 N 个键,并且b有 M 个键,则花费的时间是 O(NM)。虽然您可以在恒定时间内检查“key 是否k存在于 dict 中”,但如果不迭代整个 dict ,则无法检查“是否存在任何以 dictb开头的键”。因此,如果可能很大,您可能想要搜索并编写二进制搜索,这将使时间减少到 O(N log M)。但是,如果这不是瓶颈,您最好还是坚持使用简单版本,因为它很简单。kbbsorted(b.keys())

请注意,我正在生成一个a过滤掉匹配项的新文件,而不是删除匹配项。出于多种原因,这几乎总是比就地删除更好的解决方案: * 它更容易推理。将对象视为不可变对象并对它们执行纯操作意味着您无需考虑状态如何随时间变化。例如,在原地删除的天真方法会遇到在迭代字典时更改字典的问题,这将引发异常。如果没有可变操作,这样的问题永远不会出现。* 它更容易阅读,并且(一旦你掌握了它)甚至写作。* 它几乎总是更快。

一个权衡是内存使用。就地删除实现必须复制所有键;built-a-new-dict 实现必须在内存中同时包含过滤后的 dict 和原始 dict。如果您保留 99% 的值,并且值比键大得多,这可能会伤害您。(另一方面,如果您保留 10% 的值,并且这些值与键的大小大致相同,您实际上会节省空间。)这就是为什么它“几乎总是”是一个更好的解决方案,而不是“总是”。

于 2012-10-18T20:49:55.863 回答
1
for key in list(a.keys()):
    if any(key.startswith(k) for k in b):
       del a[key]

替换key.startswith(k)为“匹配”的适当条件。

于 2012-10-18T20:41:20.923 回答
0
c={} #result in dict c
for key in b.keys():
    if all([z.count(key)==0 for z in a.keys()]): #string of the key in b should not be substring for any of the keys in a
       c[key]=b[key]
于 2012-10-18T20:39:44.910 回答