2017-07-08 31 views
2

如何将常用值的字典的键合并到元组中。例如:合并单个字典的常见值的密钥的Python方式

A = {'E2': {'5', '7'}, 'E3': {'4', '8'}, 'E5': {'5', '7'}, 'E8': {'4', '8'}} 

output = {('E2', 'E5'): {'5', '7'}, ('E3', 'E8'): {'4', '8'}} 

我尝试:

A = {'E2': {'5', '7'}, 'E3': {'4', '8'}, 'E5': {'5', '7'}, 'E8': {'4', '8'}} 

output = {} 
seen = [] 
for k, v in A.items(): 
    if v not in [s[1] for s in seen]: # not seen this value yet 
     print('NOT SEEN') 
     print(k, v) 
     seen.append([k,v]) 
     output[k] = v 
    else: # already seen it 
     print('SEEN') 
     print(k, v) 
     # determine where we've seen it 
     where = [x for x in seen if x[1]==v] 
     output.pop(where[0][0]) 
     output[(where[0][0], k)] = v 


print('OUTPUT = ', output)  

此打印:

OUTPUT = {('E2', 'E5'): {'7', '5'}, ('E3', 'E8'): {'4', '8'}} 
+2

好吧,有什么阻止你这样做呢?你有具体的问题吗? – vaultah

+1

@vaultah转述为问题 –

+1

我们说我们希望看到您的努力。 “给我代码”这类问题一般都会被忽视。尤其是当一个或两个回路足以解决问题时。 –

回答

2

你可以试试这个:

from collections import defaultdict 

A = {'E2': {'5', '7'}, 'E3': {'4', '8'}, 'E5': {'5', '7'}, 'E8': {'4', '8'}} 

second_new = defaultdict(list) 

for a, b in A.items(): 
    second_new[tuple(b)].append(a) 

final_dict = {tuple(b):set(a) for a, b in second_new.items()} 

输出:

{('E8', 'E3'): {'8', '4'}, ('E5', 'E2'): {'5', '7'}} 
+0

错了......尝试在发布之前运行代码... –

+1

@Pii请参阅我最近的编辑。 – Ajax1234

+0

谢谢。这是最简单和容易理解的。 –

2
import itertools 

A = {'E2': {'5', '7'}, 'E3': {'4', '8'}, 'E5': {'5', '7'}, 'E8': {'4', '8'}} 

def key(x): 
    # List supports ordering 
    return sorted(list(x[1])) 

def gen(): 
    for (group_key, group) in itertools.groupby(sorted(A.items(), key=key), key=key): 
     gl = list(group) 
     yield (tuple(x[0] for x in gl), 
       gl[0][1] # group_key is a list, but we want original set 
      ) 

print(dict(gen())) 

如果你准备说服自己,SET->列表 - >设置转换安全,那么你可以做一个班轮,而不是发电机:

print(dict((tuple(g[0] for g in group), set(group_key)) for 
      (group_key, group) in 
      itertools.groupby(sorted(A.items(), key=key), key=key))) 

UPD:那么,这里究竟发生了什么?

首先,我们通过调用.items()将字典转换为元组的迭代。 我们希望将具有相同第二个元素(具有索引1或前面的词典值)的此迭代项目组合在一起。 这正是itertools.groupby所做的。论点是我们将要分组的一个迭代和关键。看起来,key=lambda kv: kv[1]是要走的路。不幸的是,我们可以比较集合的平等性,但文档说可迭代应该是有序的。和sorted函数需要键可比较的顺序。无法通过列表罐来比较集合。我们可以安全地创建一个包含与set相同的元素的列表,但我们应该对它进行排序(相同的集合可以生成不同顺序的列表,{5, 7} == {7, 5},但是[5, 7] != [7, 5])。

现在,排序和分组,我们有以下数据结构之后:

[ 
    (key_dict_value as list, iterable of (dict_key, dict_value) that has dict_value == key_dict_value), 
    ... 
] 

现在,我们可以在这个迭代迭代和创建的元组的另一迭代。我们采用每个元组的第二个元素(可以迭代,索引为1)并将其转换为元组(这是我们未来字典的关键)。我们未来字典的价值是来自原始字典的价值。我们可以从元组的第二个元素的某个元素(这个迭代不能为空,因为groupby不能产生空的组,见第一个片段)或者从key_dict_value转换回列表(这是安全的,因为这个列表是从集合中产生,因此它没有相同的元素,请参阅第二个片段)。

UPD2

虽然我写的说明,我要指出的是平等的关键不是罚款sorted但罚款groupby,所以这里没有定义key功能和转换列表背部设置更简单的解决方案:

print(dict((tuple(g[0] for g in group), group_key) for 
      (group_key, group) in itertools.groupby(sorted(A.items(), 
                  key=lambda x: sorted(list(x[1]))), 
                key=lambda x: x[1]))) 
5

我会进行转型两遍:

>>> A = {'E2': {'5', '7'}, 'E3': {'4', '8'}, 'E5': {'5', '7'}, 'E8': {'4', '8'}} 

# First pass: Create a reverse one-to-many mapping. 
# The original set() value gets converted to a hashable frozenset() 
# and used as a key. The original scalar string key gets accumulated 
# in a list to track the multiple occurrences. 
>>> reverse = {} 
>>> for key, value in A.items(): 
     reverse.setdefault(frozenset(value), []).append(key) 

# Second pass: reverse the keys and values. The list of matching 
# values gets converted to a hashable tuple (as specified by the OP) 
# and the frozenset() gets restored back to the original set() type. 
>>> {tuple(value) : set(key) for key, value in reverse.items()} 
{('E2', 'E5'): {'5', '7'}, ('E3', 'E8'): {'8', '4'}} 

这给出了OP所期望的输出。

请注意,输入字典没有保证的顺序,也没有原始输入中的任何集合。因此,输出不能保证条款的顺序。

1

下面是我使用comprehensions进行的工作。只需要两个中间步骤并仅使用内置数据类型。

# get unique values from original dict 
targ_values = set([tuple(v) for v in A.values()]) 

# build lists of original keys that match the temp_keys 
targ_values = {targ_value:[orig_key for orig_key, orig_value in A.items() if tuple(orig_value) == targ_value] for targ_value in targ_values} 

# reverse the order of keys & values and convert types to get desired output 
output = {tuple(v):set(k) for k, v in targ_values.items()} 
相关问题