反向字典。输出不断变化

时间:2016-03-17 20:36:57

标签: python

所以我必须编写一个接收字典作为输入参数的函数,并返回输入字典的反转,其中原始字典的值用作返回字典的键,原始字典的键用作返回字典的值。

例如,如果函数被称为

reverse_dictionary({'Accurate': ['exact', 'precise'], 'exact': ['precise'], 'astute': ['Smart', 'clever'], 'smart': ['clever', 'bright', 'talented']})

然后我的函数应该返回

{'precise': ['accurate', 'exact'], 'clever': ['astute', 'smart'], 'talented': ['smart'], 'bright': ['smart'], 'exact': ['accurate'], 'smart': ['astute']}

这是我的功能

def reverse_dictionary(input_dict):
    d={}
    def countEmpty(dictionario):
        count=0
        for k,v in dictionario.items():
            if(len(dictionario[k])==0):
                count+=1
        return count
    def removo(dicto, dicto2):
        for k,v in dicto.items():
            #v.sort()
            if (len(dicto[k])!=0):
                if v[-1] not in dicto2:
                    dicto2[v[-1].lower()]=[k.lower()]
                else:
                    dicto2[v[-1]].append(k.lower())
                dicto[k]=v[:-1]
    while countEmpty(input_dict)<len(input_dict):
        removo(input_dict,d)
    for k,v in d.items():
        v.sort()
    return d

dicta={'astute': ['Smart', 'clever', 'talented'], 'Accurate': ['exact', 'precise'], 'exact': ['precise'], 'talented': ['smart', 'keen', 'Bright'], 'smart': ['clever', 'bright', 'talented']}
print(reverse_dictionary(dicta))

该计划最初有效。它颠倒了字典。但是字典中的值需要排序。 我用以下方式测试了该程序:

dicta={'astute': ['Smart', 'clever', 'talented'], 'Accurate': ['exact', 'precise'], 'exact': ['precise'], 'talented': ['smart', 'keen', 'Bright'], 'smart': ['clever', 'bright', 'talented']}

它有时会回归:

{'keen': ['talented'], 'talented': ['astute', 'smart'], 'clever': ['astute', 'smart'], 'exact': ['accurate'], 'bright': ['smart', 'talented'], 'precise': ['accurate', 'exact'], 'smart': ['astute', 'talented']}

这是正确答案,但有时它也会返回:

{'bright': ['smart', 'talented'], 'exact': ['accurate'], 'talented': ['astute', 'smart'], 'precise': ['accurate', 'exact'], 'clever': ['astute', 'smart'], 'smart': ['astute'], 'keen': ['talented']}

有聪明的&#39;关键缺少有才能的&#39;值。即使我没有做任何改变代码的事情。我理解python中的词典确实没有任何顺序,但这些值是否应该保持一致?为什么会这样?

3 个答案:

答案 0 :(得分:0)

你可以创建一个元组的排序列表,将每个值与原始字典中的键相关联,然后使用itertools.groupby,dict comprehension和list comprehesion合并输出:

import itertools

d = {'accurate': ['exact', 'precise'],
     'exact': ['precise'], 
     'astute': ['smart', 'clever'],
     'smart': ['clever', 'bright', 'talented']}

l = sorted([(v2,k) for k, v in d.items() for v2 in v])

{k:list(x[1] for x in g) for k, g in itertools.groupby(l, lambda x: x[0])}

中级清单l:

[('bright', 'smart'),
 ('clever', 'astute'),
 ('clever', 'smart'),
 ('exact', 'accurate'),
 ('precise', 'accurate'),
 ('precise', 'exact'),
 ('smart', 'astute'),
 ('talented', 'smart')]

输出:

{'bright': ['smart'],
 'clever': ['astute', 'smart'],
 'exact': ['accurate'],
 'precise': ['accurate', 'exact'],
 'smart': ['astute'],
 'talented': ['smart']}

答案 1 :(得分:0)

我能够重现输出不一致的错误。您的算法可能存在两个问题。

  1. 您假设密钥将按顺序迭代。
  2. 您正在迭代对象,同时对其进行修改。这在Python 3.X中尤其奇怪,其中items返回项的视图而不是显式的可迭代(参见this question)。
  3. 您似乎可以使用以下行“解决”这两个问题:

    for k,v in sorted(dicto.items()):
    

    这在我的测试中提供了一致,正确的输出。我对为什么这个有用并不​​十分自信,而且缺乏解释可能会说明为什么你不应该迭代一个不断变化的对象开始。

    为了好玩,这是一个不同的,asinine解决方案:

    import networkx as nx
    
    d = {
        'Accurate': ['exact', 'precise'], 
        'exact': ['precise'], 
        'astute': ['Smart', 'clever'], 
        'smart': ['clever', 'bright', 'talented']
    }
    
    # make keys uppercase and values lowercase
    d = {k.upper(): list(map(str.lower, v)) for k,v in d.items()}
    
    # fill out all of the edges
    expanded = nx.convert.to_dict_of_lists(nx.Graph(d))
    
    # convert the uppercase values to lowercase and filter out the uppercase keys
    filtered = {k: list(map(str.lower, v)) for k,v in expanded.items() if k.islower()}
    

答案 2 :(得分:0)

您正在获取未排序的输出,因为词典未按设计排序。以可预测的顺序查看密钥的唯一方法是使用collections.OrderedDict(替换dict),它只是按插入顺序显示它们。你每次都得到 不同的输出,因为python的设计者作为一种抵御拒绝服务攻击的安全措施,在密钥的顺序中引入了非确定性组件。存储并返回。

如果字典中的值列表已经排序,您可以在检索时简单地对键进行排序:

revdict = reverse_dictionary(dicta)
for k in sorted(revdict):
    print(k, revdict[k])

或等效(因为元组首先按第一个元素排序):

revdict = reverse_dictionary(dicta)
for k, v in sorted(revdict.items()):
    print(k, v)