【问题标题】:Remove values from lists of values in a dictionary从字典中的值列表中删除值
【发布时间】:2016-05-12 05:45:56
【问题描述】:

我在 Windows 7 中使用 Python 2.7。

我有一本字典,想从另一个字典中删除对应于(键、值)对的值。

例如,我有一本字典t_dict。我想删除字典 values_to_remove 中对应的(键、值)对,这样我就得到了字典 final_dict

t_dict = {
    'a': ['zoo', 'foo', 'bar'],
    'c': ['zoo', 'foo', 'yum'],
    'b': ['tee', 'dol', 'bar']
}

values_to_remove = {
    'a': ['zoo'],
    'b': ['dol', 'bar']
}

# remove values here

print final_dict
{
    'a': ['foo', 'bar'],
    'c': ['zoo', 'foo', 'yum'],
    'b': ['tee']
}

我查看了关于 SO 和 python 词典文档的类似页面,但找不到任何解决此特定问题的方法:

https://docs.python.org/2/library/stdtypes.html#dict

How to remove dictionaries with duplicate values from a nested dictionary

How to remove a key from a python dictionary?

编辑

每个键的t_dict 中不能有重复值。例如永远不会有

t_dict['a'] = ['zoo','zoo','foo','bar']

【问题讨论】:

  • 您没有从字典中删除值。您正在从 list 中删除值。
  • for key, list_ in values_to_remove.items(): for word in list_: t_dict[key].remove(word)
  • 可以有像 t_dict['a']=['foo','foo'] 和 values_to_remove['a']=['foo'] 这样的重复项吗?
  • @sasha,好问题,不,不可能。我将编辑我的 OP

标签: python python-2.7 dictionary


【解决方案1】:

试试这个,

for k, v in t_dict.items():
    for item in values_to_remove.get(k, ()):
        v.remove(item) 

# Output
{'a': ['foo', 'bar'], 'c': ['zoo', 'foo', 'yum'], 'b': ['tee']}

【讨论】:

  • 您不应该在if 内循环以删除与values_to_remove 中的k 关联的所有值吗?或者通过结合检查和迭代来简化代码,for k, v in t_dict.items():for toremove in values_to_remove.get(k, ()):v.remove(toremove)(这也避免了第二次不必要地查找t_dict[k];你已经从items迭代中得到了它)。跨度>
【解决方案2】:

由于不可能重复,将值存储为set,而不是list 可能是有意义的。如果您可以将set 用于t_dict,则删除过程会更快更简单(如果values_to_remove 也使用setfrozenset 则更快):

for k, toremove in values_to_remove.viewitems():
    t_dict.get(k, set()).difference_update(toremove)

如果values_to_remove 预计很小,或者t_dict 更小,则使用上面的,您可以切换到以下以避免临时的set()s(空的tuple 是一个单例,所以它成本dict.get):

for k, v in t_dict.viewitems():
    v.difference_update(values_to_remove.get(k, ()))

最后一个选项是一种非常聪明的方法,它完全不需要使用.get,只需处理出现在两个dicts 中的键(使用-= 需要两个dicts 才能使用set值更短/更快,如果您想允许非sets 用于values_to_remove 的值,您可以返回difference_update):

for k in (t_dict.viewkeys() & values_to_remove.viewkeys()):
    t_dict[k] -= values_to_remove[k]

【讨论】:

  • 如果订单很重要,请使用OrderedSet
  • @sparkandshine: OrderedSet 不是 Python 标准库的一部分(它只有 collections.OrderedDict 可用于模拟大多数 set 行为 except我在这里使用的特定于设置的操作),但是,如果您对附加依赖项没问题,OrderedSet 是一个选项。
【解决方案3】:
for key,values in values_to_remove.items():
    for value in values:
        if key in t_dict and value in t_dict[key]:
            t_dict[key].pop(t_dict[key].index(value))

【讨论】:

  • 不符合要求。您不会丢弃整个列表,而是弹出匹配的元素。
  • 原始问题中没有列表。感谢您的反对
  • 如果 StackOverflow 没有保留编辑历史记录,我可以很容易地看到唯一被编辑的是问题标题,那将是一个很好的借口。
  • 我指的是 OP 中提出的第一个 question,而不是 OP 的第一个 version
  • @Two-BitAlchemist:不一定。在发布答案/cmets 或投票之前进行的编辑通常不会出现在历史记录中。因此,您可以加载一个问题,撰写答案,并在撰写时,“静默”地编辑问题。不知道这里是否是这种情况,但它可能是。
【解决方案4】:

当您不想在 dict 中包含重复的元素,并且顺序也不那么重要时,为什么不使用 set 作为您的 dic 值?

t_dict = {
    'a': set(['zoo', 'foo', 'bar']),
    'c': set(['zoo', 'foo', 'yum']),
    'b': set(['tee', 'dol', 'bar'])
}

values_to_remove = {
    'a': set(['zoo']),
    'b': set(['dol', 'bar'])
}

for k,v in values_to_remove.iteritems():
    t_dict[k] = t_dict[k]-v

print t_dict

>>>{'a': set(['foo', 'bar']), 'c': set(['foo', 'yum', 'zoo']), 'b': set(['tee'])}

如果订单对您很重要,您还可以在建议的评论中使用像@sparkandshine 这样的 OrderedSet。 http://orderedset.readthedocs.io/en/latest/

from ordered_set import OrderedSet
t_dict = {
    'a': OrderedSet(['zoo', 'foo', 'bar']),
    'c': OrderedSet(['zoo', 'foo', 'yum']),
    'b': OrderedSet(['tee', 'dol', 'bar'])
}

values_to_remove = {
    'a': OrderedSet(['zoo']),
    'b': OrderedSet(['dol', 'bar'])
}

for k,v in values_to_remove.iteritems():
    t_dict[k] = t_dict[k]-v

print t_dict

>>>{'a': OrderedSet(['foo', 'bar']), 'c': OrderedSet(['zoo', 'foo', 'yum']), 'b': OrderedSet(['tee'])}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-09-28
    • 1970-01-01
    • 1970-01-01
    • 2019-09-08
    • 2018-05-01
    • 1970-01-01
    相关资源
    最近更新 更多