有效地交换python dict的键和值,其中值包含一个或多个元素

时间:2021-11-23 18:09:30

Suppose I have a dict:

假设我有一个词典:

x =  { "a": ["walk", "the", "dog"], "b": ["dog", "spot"], "c":["the", "spot"]  }

and want to have the new dict:

并希望有新的词典:

y = { "walk": ["a"], "the": ["a", "c"], "dog":["a", "b"], "spot":["b","c"]  }

What is the most efficient way to do this? If a solution is a few lines and is somehow made simple by a pythonic construct what is it (even if it's not most efficient)?

最有效的方法是什么?如果解决方案是几行并且通过pythonic构造以某种方式简化它是什么(即使它不是最有效的)?

Note that this is different than other questions where the value is a single element and not a list.

请注意,这与其他值是单个元素而不是列表的问题不同。

3 个解决方案

#1


5  

You can use defaultdict:

你可以使用defaultdict:

from collections import defaultdict

y = defaultdict(list)

for key, values in x.items():  # .iteritems() in Python 2
    for value in values:
        y[value].append(key)

#2


2  

y = {}
for (k, v) in x.iteritems():
    for e in v:
        y.setdefault(e, []).append(k)

I presented this as an alternative to @Blender's answer, since it's what I'm accustomed to using, but I think Blender's is superior since it avoids constructing a temporary [] on every pass of the inner loop.

我把它作为@Blender答案的替代品,因为它是我习惯使用的,但我认为Blender是优越的,因为它避免在内循环的每次传递中构造临时[]。

#3


1  

Not necessarily efficient, but a one liner just for fun:

不一定高效,但只是为了好玩的一个班轮:

{b: [k for k, w in x.iteritems() if b in w] for v in x.values() for b in v}

The idea here is to iterate over all the values in the original dictionary (for v in x.values()), then iterate over all the items in the list (for b in v), then use b as the key in a dict-comprehension. The value for b is a list comprehension [k for ...] where the members are the keys in dictionary x for which the value w contains the word b.

这里的想法是迭代原始字典中的所有值(对于x.values()中的v),然后遍历列表中的所有项(对于v中的b),然后使用b作为字典中的键-理解。 b的值是列表推导[k for ...],其中成员是字典x中的键,其值w包含单词b。

Because the scope is limited you can actually write v instead of w above, which makes it even harder to understand. :-)

因为范围是有限的,你实际上可以写v而不是上面的w,这使得它更难理解。 :-)

(Edit to add, I'd use @Blender's. These one liners are fun, but really hard to grok.)

(编辑添加,我会使用@Blender's。这些衬里很有趣,但很难理解。)

#1


5  

You can use defaultdict:

你可以使用defaultdict:

from collections import defaultdict

y = defaultdict(list)

for key, values in x.items():  # .iteritems() in Python 2
    for value in values:
        y[value].append(key)

#2


2  

y = {}
for (k, v) in x.iteritems():
    for e in v:
        y.setdefault(e, []).append(k)

I presented this as an alternative to @Blender's answer, since it's what I'm accustomed to using, but I think Blender's is superior since it avoids constructing a temporary [] on every pass of the inner loop.

我把它作为@Blender答案的替代品,因为它是我习惯使用的,但我认为Blender是优越的,因为它避免在内循环的每次传递中构造临时[]。

#3


1  

Not necessarily efficient, but a one liner just for fun:

不一定高效,但只是为了好玩的一个班轮:

{b: [k for k, w in x.iteritems() if b in w] for v in x.values() for b in v}

The idea here is to iterate over all the values in the original dictionary (for v in x.values()), then iterate over all the items in the list (for b in v), then use b as the key in a dict-comprehension. The value for b is a list comprehension [k for ...] where the members are the keys in dictionary x for which the value w contains the word b.

这里的想法是迭代原始字典中的所有值(对于x.values()中的v),然后遍历列表中的所有项(对于v中的b),然后使用b作为字典中的键-理解。 b的值是列表推导[k for ...],其中成员是字典x中的键,其值w包含单词b。

Because the scope is limited you can actually write v instead of w above, which makes it even harder to understand. :-)

因为范围是有限的,你实际上可以写v而不是上面的w,这使得它更难理解。 :-)

(Edit to add, I'd use @Blender's. These one liners are fun, but really hard to grok.)

(编辑添加,我会使用@Blender's。这些衬里很有趣,但很难理解。)