键和值的可能组合,没有重复项

时间:2019-05-01 07:55:03

标签: python

我试图从字典(无重复项)中获得键(str)和对应值(str)的所有唯一组合(不是顺序不重要的排列)。

items_dict = {
    'item1': {'value1', 'value2', 'value3'},
    'item2': {'value1', 'value4'},
    'item3': {'value5', 'value2', 'value6', 'value1'}
}

我将这些值放在集合中,以便可以将它们合并。也许使用字典和集不是解决它的正确方法。

我尝试过:

comb = combinations((items_dict.items()), 2)

但是得到了键和值的元组:

(('item2': {'value1', 'value4'}), ('item1': {'val ...

我需要预期的结果看起来像这样,以识别键和分隔的相应值的组合:

'item1', 'item2': {'value1', 'value2', 'value3', 'value4'}
'item2', 'item 3': {'value5', 'value2', 'value6', 'value1', 'value4'}
'item3', 'item1': {'value1', 'value2', 'value3', 'value5', 'value6'}

2 个答案:

答案 0 :(得分:3)

因此,您需要键的itertools.combinations结果,然后是这些键的值的组合集。

import itertools
from typing import Mapping, Tuple, Any

def get_combinations(d: Mapping[Any, set]) -> Mapping[Tuple[Any, Any], set]:
    """Combine keys into pairs and merge values together.

    >>> d = {1: {1, 2}, 2: {3, 4}, 3: {1, 4}}
    >>> get_combinations(d)
    {(1, 2): {1, 2, 3, 4}, (1, 3): {1, 2, 4}, (2, 3): {1, 3, 4}}
    """

    key_combos = itertools.combinations(d.keys(), 2)

    result = {key_combo: set.union(*(d[key] for key in key_combo)) for key_combo in key_combos}
    return result

答案 1 :(得分:2)

您可以将其打包成字典理解:

from itertools import combinations

items_dict = {
    'item1': {'value1', 'value2', 'value3'},
    'item2': {'value1', 'value4'},
    'item3': {'value5', 'value2', 'value6', 'value1'}
}

res = {(key1, key2):  value1 | value2 
       for (key1, value1), (key2, value2) in combinations(items_dict.items(), r=2)}
 # {('item1', 'item2'): {'value4', 'value3', 'value2', 'value1'}, 
 #  ('item1', 'item3'): {'value5', 'value3', 'value6', 'value2', 'value1'}, 
 #  ('item2', 'item3'): {'value4', 'value5', 'value6', 'value2', 'value1'}}

使用frozenset作为新字典的键可能更有用:

res = {frozenset((key1, key2)):  value1 | value2 
       for (key1, value1), (key2, value2) in combinations(items_dict.items(), r=2)}
# {frozenset({'item1', 'item2'}): {'value2', 'value4', 'value1', 'value3'}, 
#  frozenset({'item1', 'item3'}): {'value2', 'value1', 'value3', 'value5', 'value6'}, 
#  frozenset({'item3', 'item2'}): {'value2', 'value4', 'value1', 'value5', 'value6'}}

通过这种方式,您可以在不知道combinations产生顺序的情况下访问值:

# those will be the same
res[frozenset(('item3', 'item1'))]
res[frozenset(('item1', 'item3'))]

如果您需要组合两个以上的项目,可以按照以下方法进行调整:

res = {frozenset(k[0] for k in kv): set.union(*(v[1] for v in kv)) 
       for kv in combinations(items_dict.items(), r=2)}