Удалить словарь из другого словаря (странное поведение в python 3)

#python #python-3.x #dictionary

#python #python-3.x #словарь

Вопрос:

У меня есть два dict

 runde = {
    "A": ["1, 2, 3", "4, 5, 6"],
    "B": ["1, 2, 3", "4, 5, 6"],
    "C": ["1, 2, 3", "4, 5, 6"],
    "D": ["1, 2, 3", "4, 5, 6"],
}

bilete = {
    "B": ["1, 2, 3", "4, 5, 6"],
    "C": ["1, 2, 3", "4, 5, 6"],
}
 

Я хочу вычесть bilete из runde с результатом

 runde = {
    "A": ["1, 2, 3", "4, 5, 6"],
    "B": [],
    "C": [],
    "D": ["1, 2, 3", "4, 5, 6"],
}
 

Код

 for key in runde:
    if key in bilete:
        b = bilete[key]
        for a in b:
            runde[key].remove(a)
 

Этот код работает нормально, но в моей ситуации после first .remove результат

 {'A': ['4, 5, 6'],'B': ['4, 5, 6'],'C': ['4, 5, 6'],'D': ['4, 5, 6']}
 

после second .remove результат

 {'A': [],'B': [],'C': [],'D': []}
 

и тогда я получаю ошибку ValueError: list.remove(x): x нет в списке

Это моя ситуация, любая помощь будет с благодарностью:

 import pickle
# here is my variables saved: import.pkl
# https://drive.google.com/file/d/1SbJm9J5dFQgc1H6m8C6epqDLAs2m15lS/view?usp=sharing
with open('import.pkl', 'rb') as f:
    runde, bilete = pickle.load(f)
for key in runde:
    if key in bilete:
        b = bilete[key]
        for a in b:
            runde[key].remove(a)
 

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

1. Никогда не изменяйте структуры, которые вы в данный момент перебираете.

2. Я не понимаю проблем, которые, как вы утверждаете, видите, и не получаю ошибку. Я думаю, что данные, которые, как вы утверждаете, есть, это совсем не то, что у вас есть.

3. @AKX Это не имеет ничего общего с изменением коллекции, которую вы перебираете. Обработка, подразумеваемая выше, не влияет на ключи, над которыми она выполняется.

4. Вы можете попробовать: for key in list(runde.keys())

5. Можете ли вы напечатать, что именно вы получаете после чтения из import.pkl

Ответ №1:

Если я введу этот код:

 runde = {
    "A": ["1, 2, 3", "4, 5, 6"],
    "B": ["1, 2, 3", "4, 5, 6"],
    "C": ["1, 2, 3", "4, 5, 6"],
    "D": ["1, 2, 3", "4, 5, 6"],
}

bilete = {
    "B": ["1, 2, 3", "4, 5, 6"],
    "C": ["1, 2, 3", "4, 5, 6"],
}

for key in runde:
    if key in bilete:
        b = bilete[key]
        for a in b:
            runde[key].remove(a)

print(runde)
 

Я получаю этот вывод:

 {'A': ['1, 2, 3', '4, 5, 6'], 'B': [], 'C': [], 'D': ['1, 2, 3', '4, 5, 6']}
 

Я пытаюсь точно угадать, какие данные у вас есть, но пока я не смог воспроизвести ваши точные симптомы.

Если, однако, я ввожу этот код:

 first = "1, 2, 3"
second = "4, 5, 6"
coll = [first, second]
runde = {
    "A": coll,
    "B": coll,
    "C": coll,
    "D": coll,
}

bilete = {
    "B": coll,
    "C": coll,
}

for key in runde:
    if key in bilete:
        b = bilete[key]
        for a in b:
            runde[key].remove(a)
            print(runde)

print(runde)
 

Я получаю этот вывод:

 {'A': [], 'B': [], 'C': [], 'D': []}
 

и никакой ошибки.

Кроме того, если я вставлю этот код перед всеми циклами:

 import copy
for k in runde:
    runde[k] = copy.deepcopy(runde[k])
 

затем вывод возвращается к желаемому результату.

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

1. И почему runde[«B»].удалить(«1, 2, 3»), удалить «1, 2, 3» из всего словаря, а не только из ключа B?

2. Это потому, что, как я показываю, коллекции — это одна и та же коллекция. Когда вы удаляете из одного, вы удаляете из всех, потому что они одинаковы. Кроме того, смотрите мое второе обновление.

3. Теперь работает нормально! Спасибо! 🙂

4. Спасибо @quamrana, теперь я вспоминаю теорию, после вашего сообщения.

Ответ №2:

Похоже, вы получаете разные словари во время чтения

 with open('import.pkl', 'rb') as f:
runde, bilete = pickle.load(f)
 

Опубликованный вами код должен возвращать правильный результат.