jprince14
jprince14

Reputation: 301

Python Identify Duplicate Dictionary Keys

In python I am looking for a way to receive a warning or error when loading a statically declared dictionary from a file that contains duplicate keys, for my use case the file is from user input so I want to make sure the dictionaries I receive dont have duplicate keys. I get that after the load dictionary1 is the same as dictionary 2 and that python dictionaries keep the rightmost key/value pair. What I am looking for is a way to get a warning or error before or during the load which indicates that dictionary1 had multiple duplicate "a" keys.

dictionary1 = {"a":1, "a":2, "a":3}
dictionary2 = {"a":3}

The best idea that I can think of is using a list of dictionaries and then adding each dictionary to the final dictionary such as the example below. This works but the list of dictionaries is not as user-friendly as just standard dictionaries.

listofDicts = [{"a":1},{"a":2},{"a":3}]
masterDict = {}
for entry in listofDict:
    for subDict in entry:
        if subDict in masterDict.keys():
            print ("ERROR key \"%s\" already exists with value %d" % (subDict, masterDict[subDict]))
        else:
            masterDict.update({subDict:entry[subDict]})

Upvotes: 1

Views: 458

Answers (1)

Blender
Blender

Reputation: 298106

You can use the ast module to parse the Python source code in your files containing the dictionaries and look for dictionary literals with duplicate keys:

import ast
import logging

class DuplicateKeyVisitor(ast.NodeVisitor):
    def visit_Dict(self, node):
        seen_keys = set()

        for key_node in node.keys:
            try:
                key = ast.literal_eval(key_node)
            except ValueError:
                continue

            if key in seen_keys:
                logging.warning('Dictionary literal at (%d, %d) has duplicate keys', node.lineno, node.col_offset)

            seen_keys.add(key)

DuplicateKeyVisitor().visit(ast.parse('''
foo = {'a': 1, 'a': 2}
bar = {'a': 1, 'b': 2}
bar = {'a': 1, 'b': 2, 'a': 3}
'''))

Upvotes: 2

Related Questions