【问题标题】:check dictionary for doubled keys [duplicate]检查字典的双键[重复]
【发布时间】:2012-10-10 23:54:14
【问题描述】:

可能重复:
How to raise error if duplicates keys in dictionary

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

{'a':1, ..., 'a':2}

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

问题是我将来如何防止这种情况发生。我认为这在 python 中是不可能的。我用过

grep "'.*'[ ]*:" myfile.py | sort | uniq -c | grep -v 1

这不是防弹的。任何其他想法(在 python 中,这个 grep 只是为了说明我的尝试)?

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

【问题讨论】:

  • 您的数据中是否存在重复键的问题?这意味着您希望标记它们(或忽略重复项)。
  • 最简单的方法是创建和使用 dict 的自定义子类(请参阅上面问题的链接),当您尝试添加重复键时,该子类会失败并显示信息性错误消息。如果这确实是您想要的,您甚至可以修改行为以忽略重复项。
  • 现在我看到这实际上是一个骗子,链接的答案解决了我的问题。我想知道为什么这种行为(通知用户他正在复制键)在 Python 中不是默认的,我无法想象双键是可取的情况。我应该关闭/删除这个问题吗? (怎么做?)
  • 内存中的dict 对象不能包含重复的键(具有相同哈希的相同对象)。如何将字典序列化为文件?

标签: python linux


【解决方案1】:

字典不能包含双键。所以你需要做的就是执行代码,然后转储dict的repr()

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

【讨论】:

  • 问题是 dict can 包含双键,正如我的问题所展示的那样,但它会默默地重新分配新值。 repr() 将如何帮助我?请记住,字典很大,我无法通过查看转储数据的 MB 来推断任何内容。我发现您答案的第二部分很有价值,尽管它会降低我的代码的可读性。谢谢
  • 它不会检测到它们,但你可以创建一个没有这些欺骗的新字典。
  • @user35186:Python 字典不能包含重复键。另一方面,Dictionary Display 基本上是一种可用于构造字典的字符串表示形式,可以包含它们。这就是您在问题中显示的内容。您需要检测正在创建的字典显示中的重复项。
  • 对不起,我没有说清楚,当然它不能像您和其他人指出的那样在内存中包含重复的键,但它可以在代码中,在其字符串表示中并产生有效(但具有误导性)语法。
【解决方案2】:

如果您需要每个键有多个值,您可以使用 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']})

【讨论】:

    【解决方案3】:

    您是否正在生成一个包含巨大字典的 Python 文件?比如:

    print "{"
    for lines in file:
        key, _, value = lines.partition(" ")
        print "    '%s': '%s',"
    print "}"
    

    如果是这样,您无法阻止这种情况发生,因为您无法轻易覆盖内置 dict 的构造。

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

    dict(a = '1', a = '2')
    

    ..如果密钥重复,它将生成SyntaxError。但是,它们并不完全等效,因为字典键比关键字参数灵活得多(例如 {123: '...'} is valid, butdict(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
    

    【讨论】:

      【解决方案4】:

      您没有确切地说或显示您是如何生成 dictionary display 的,而重复键出现的位置。但这就是问题所在。

      我建议您使用这种形式:dict([['a', 1], ..., ['a', 2]]),而不是使用类似 {'a':1, ..., 'a':2} 的东西来构建字典,它将从提供的 [key, value] 对列表中创建一个。这种方法将允许您在将其传递给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))
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2011-08-26
        • 2013-09-22
        • 1970-01-01
        • 2016-09-29
        • 1970-01-01
        • 2013-10-15
        • 2012-06-15
        • 2019-04-19
        相关资源
        最近更新 更多