Python 检查字典中的双键

Python 检查字典中的双键,python,linux,Python,Linux,可能重复: 我最近正在生成包含数十万个键的大型词典(因此通过查看它们来发现错误是不可行的)。它们在语法上是正确的,但在某个地方有一个bug。它归结为“重复键”: 这段代码编译得很好,我不明白为什么a键的值是2,正如我所期望的1。现在问题很明显 问题是我今后如何防止这种情况发生。我认为这在python中是不可能的。我曾经 grep "'.*'[ ]*:" myfile.py | sort | uniq -c | grep -v 1 这不是防弹的。还有其他想法吗(在python中,这个grep只

可能重复:

我最近正在生成包含数十万个键的大型词典(因此通过查看它们来发现错误是不可行的)。它们在语法上是正确的,但在某个地方有一个bug。它归结为“重复键”:

这段代码编译得很好,我不明白为什么
a
键的值是
2
,正如我所期望的
1
。现在问题很明显

问题是我今后如何防止这种情况发生。我认为这在python中是不可能的。我曾经

grep "'.*'[ ]*:" myfile.py | sort | uniq -c | grep -v 1
这不是防弹的。还有其他想法吗(在python中,这个grep只是为了说明我所尝试的)


编辑:我不想要重复的键,只需要发现这种情况并手动编辑数据

dict不能包含双键。因此,您只需执行代码,然后转储dict的
repr()


另一个选项是将dict项创建为
(键,值)
元组。通过将它们存储在一个列表中,您可以轻松地从它们创建一个dict,然后检查dict/列表的
len()
s是否不同。

如果您需要每个键有多个值,您可以使用defaultdict将值存储在一个列表中

>>> from collections import defaultdict
>>> data_dict = defaultdict(list)
>>> data_dict['key'].append('value')
>>> data_dict
defaultdict(<type 'list'>, {'key': ['value']})
>>> data_dict['key'].append('second_value')
>>> data_dict
defaultdict(<type 'list'>, {'key': ['value', 'second_value']})
>>从集合导入defaultdict
>>>数据目录=默认目录(列表)
>>>数据dict['key'].追加('value')
>>>数据字典
defaultdict(,{'key':['value']})
>>>数据dict['key'].append('second'u value')
>>>数据字典
defaultdict(,{'key':['value','second_value']})

您是否正在生成包含大型词典的Python文件?比如:

print "{"
for lines in file:
    key, _, value = lines.partition(" ")
    print "    '%s': '%s',"
print "}"
如果是这样的话,您就没有什么办法来防止这种情况,因为您无法轻松覆盖内置的dict的构造

相反,我建议您在构造字典字符串时验证数据。您还可以生成不同的语法:

dict(a = '1', a = '2')
…如果密钥重复,将生成一个
语法错误
。但是,它们并不完全相同,因为字典键比关键字args灵活得多(例如,
{123:''.''''''.}是有效的,但是
dict(123='.'''''.'是错误的)

您可以生成如下函数调用:

uniq_dict([('a', '...'), ('a', '...')])
然后包括函数定义:

def uniq_dict(values):
    thedict = {}

    for k, v in values:
        if k in thedict:
            raise ValueError("Duplicate key %s" % k)
        thedict[k] = v

     return thedict

您没有确切说明或显示如何生成重复关键点所在的位置。但这就是问题所在

我建议您不要使用类似于
{'a':1,,'a':2}
的方式来构建字典,而是使用以下形式:
dict([['a',1],…,['a',2]])
,它将从提供的
[键,值]
对列表中创建一个字典。这种方法允许您在将对列表传递给
dict()
以实际构建字典之前,检查对列表中是否有重复项

以下是检查配对列表中是否存在重复项的一种方法示例:

sample = [['a', 1], ['b', 2], ['c', 3], ['a', 2]]

def validate(pairs):
    # check for duplicate key names and raise an exception if any are found
    dups = []
    seen = set()
    for key_name,val in pairs:
        if key_name in seen:
            dups.append(key_name)
        else:
            seen.add(key_name)
    if dups:
        raise ValueError('Duplicate key names encountered: %r' % sorted(dups))
    else:
        return pairs

my_dict = dict(validate(sample))

您的数据中是否存在重复密钥的问题?这意味着您希望对它们进行标记(或忽略重复项)。最简单的方法是创建并使用dict的自定义子类(请参见上面问题的链接),当您尝试添加重复项时,该子类将失败,并显示信息性错误消息。你甚至可以修改行为来忽略重复,如果这是你真正想要的。现在我看到这实际上是一个重复,这个答案解决了我的问题。我想知道为什么这样的行为(通知用户他正在复制密钥)在Python中不是默认的,我无法想象需要将密钥加倍的情况。我是否应该关闭/删除此问题?(如何?)内存中的
dict
对象不能包含重复的键(具有相同哈希的相等对象)。如何将字典序列化为文件?问题是dict可以包含双键,正如我的问题所示,但它会以静默方式重新分配新值。
repr()
将如何帮助我?请记住,字典是巨大的,我无法通过查看转储数据的MBs来推断任何内容。我觉得你答案的第二部分很有价值,尽管它会降低我代码的可读性。ThanksIt不会检测到它们,但您可以创建一个没有这些重复项的新dict。@user35186:Python字典不能包含重复的键。另一方面,基本上是一个字符串表示,可以用来构造字典,可以包含它们。这就是你在问题中表现出来的。您需要在正在创建的字典显示中检测重复项。抱歉,我没有说清楚,当然它不能像您和其他人指出的那样在内存中包含重复的键,但它可以在代码中、在字符串表示中,并生成有效(但误导)语法。
sample = [['a', 1], ['b', 2], ['c', 3], ['a', 2]]

def validate(pairs):
    # check for duplicate key names and raise an exception if any are found
    dups = []
    seen = set()
    for key_name,val in pairs:
        if key_name in seen:
            dups.append(key_name)
        else:
            seen.add(key_name)
    if dups:
        raise ValueError('Duplicate key names encountered: %r' % sorted(dups))
    else:
        return pairs

my_dict = dict(validate(sample))