Как добавить в список в словаре в списке, как определено другим ключом?

#python #dictionary

Вопрос:

У меня есть список словарей с ключом для имени и ключом для списка элементов (среди других ключей). У меня есть функция с параметрами имени и элемента. Словари проверяются на соответствие имени, и если элемент соответствует заданному набору, он становится основным элементом. В противном случае, если он соответствует другому заданному набору для разных элементов, он добавляется в список «Другие элементы».

В нынешнем виде мой код в настоящее время, похоже, добавляет эти разные элементы универсально, поскольку выходные данные всех словарей в конце содержат один и тот же список других элементов для всех перечисленных словарей. Обновление основного элемента, похоже, работает нормально, но я не могу заставить другие элементы функционировать должным образом. Ниже приведено несколько примеров.

 personList = []
personStats = {"Name": "", "MainItem": "", "OtherItems": []}
 

Измененное имя-уникальные копии personStats добавляются в список персон, как указано выше, для каждого человека и работают по назначению.

 def updatePersonItem(name, item):
    itemType = verifyPersonItem(item)
    if itemType == "Main":
        for person in personList:
            if person["Name"] == name:
                person["MainItem"] = name  
    elif itemType == "Misc":
        for person in personList:
            if person["Name"] == name:
                if item not in personStats["OtherItems"]:
                    person["OtherItems"].append(item)
 

Функция verifyPersonItem() сравнивает элемент с 2 различными наборами и возвращает Main или Разное. Я также написал другие итерации updatePersonItem (), которые все равно приводят к тому же результату.

Хотя мне это кажется хорошим, выполнение приведенного выше кода и печать списка лиц выводят результаты, аналогичные приведенным ниже.

 {"Name": "Bob", "MainItem": "Bag", "OtherItems": ['apple', 'banana', 'mandarin', 'orange', 'pear']}
{"Name": "Alice", "MainItem": "Lunchbox", "OtherItems": ['apple', 'banana', 'mandarin', 'orange', 'pear']}
 

Тем не менее, я ожидаю вывода, подобного приведенному ниже, где по назначению добавляются только применимые элементы.

 {"Name": "Bob", "MainItem": "Bag", "OtherItems": ['apple', 'orange', 'pear']}
{"Name": "Alice", "MainItem": "Lunchbox", "OtherItems": ['apple', 'mandarin']
 

Any ideas?

Edit: I have found a workaround that seems to function as intended. See below.

 def updatePersonItem(name, item):
    itemType = verifyPersonItem(item)
    for person in personList:
        if person["Name"] == name: 
            if itemType == "Main":
                person["Main"] = item     
            elif itemType == "Misc":
                if item not in person["OtherItems"]:
                    personOtherItemCopy = person["OtherItems"].copy()
                    personOtherItemCopy.append(item)
                    person["Misc"] = personOtherItemCopy
 

Edit2: Я добавил минимальный воспроизводимый пример моего исходного кода, чтобы смоделировать мой исходный сценарий в соответствии с просьбой. Надеюсь, это приведет к лучшему решению.

 import re 

personList = []
personStats = {"Name": "", "MainItem": "", "OtherItems": []}

def addPerson(name):
    if not any(d["Name"] == name for d in personList):
        personStatsCopy = personStats.copy()
        personStatsCopy.update({"Name": name})
        personList.append(personStatsCopy)
    else:
        updatePlayerClass(name, item)

def verifyPersonItem(item):
    verifyItemPattern = re.compile(r'(Lunchbox|Bag|Bento|Apple|Orange|Mandarin|Banana|Pear)')
    classMatch = re.search(verifyItemPattern, item)
    boolean = bool(classMatch)
    if boolean == True:
        if item == "Lunchbox" or item == "Bag" or item == "Bento":
            return ("Main")
        else:
            return ("Misc")
    else:
        print("Invalid item.")

def updatePersonItem(name, item):
    itemType = verifyPersonItem(item)
    if itemType == "Main":
        for person in personList:
            if person["Name"] == name:
                person["MainItem"] = item  
    elif itemType == "Misc":
        for person in personList:
            if person["Name"] == name:
                if item not in person["OtherItems"]:
                    person["OtherItems"].append(item)

addPerson("Bob")
addPerson("Alice")
updatePersonItem("Bob", "Bag")
updatePersonItem("Bob", "Apple")
updatePersonItem("Bob", "Orange")
updatePersonItem("Bob", "Mandarin")
updatePersonItem("Alice", "Mandarin")
updatePersonItem("Alice", "Lunchbox")
updatePersonItem("Alice", "Pear")

print(personList)
 

Комментарии:

1. сначала вы могли бы использовать print() для просмотра значений переменных, которые вы используете в функции.

2. лучше создайте минимальный рабочий код — с примерами данных, — чтобы мы могли просто скопировать и запустить его.

3. Я не понимаю, почему у вас разные переменные itemType и roleType . И person и player . возможно, вы проверяете значение для одного person , но добавляете его к другому player . ИЛИ, может быть, вы назначили один и тот же список двум людям, поэтому, когда вы добавляете элемент в одного человека, другой человек также получает этот элемент.

4. Извините, код здесь является мягкой перепиской буквального кода, я просто пропустил изменение этих переменных в новые здесь. Я нашел обходной путь, который, похоже, работает с помощью функции .copy (). Я соответствующим образом обновил сообщение.

5. новый код очень отличается — и этот код действительно показывает, что без .copy() него могут возникнуть проблемы.