итеративное добавление N элементов в список дает последний элемент N раз - PullRequest
0 голосов
/ 07 февраля 2020

Я получаю доступ к списку элементов словаря list_of_dict = [{'ka':'1a', 'kb':'1b', 'kc':'1c'},{'ka':'2a'},{'ka':'3a', 'kb':'3b', 'kc':'3c'}] и пытаюсь условно добавить каждую запись в другой список article_list, используя функцию add_entries.

Мой желаемый вывод

article_list = [{x:1a, y:1b, z:1c}, {x:2a}, {x:3a, y:3b, z:3c}]

Мой код:


def add_entries(list_of_dict):
   keys = ['x','y','z']
   #defining a temporary dictionary here
   my_dict = dict.fromkeys(keys,0)
   entry_keys = ['ka','kb','kc']

   my_list = []

   for item in list_of_dict:
    # conditionally append the entries into the temporary dictionary maintaining desired key names
        my_dict.update({a: item[b] for a,b in zip(keys, entry_keys) if b in item})
        my_list.append(my_dict)

   return my_list



if __name__ == "__main__":
   list_of_dict = [{'ka':'1a', 'kb':'1b', 'kc':'1c'},{'ka':'2a'},{'ka':'3a', 'kb':'3b', 'kc':'3c'}]
   article_list = []
   returned_list = add_entries(list_of_dict)
   article_list.extend(returned_list)

Мой вывод

article_list = [{x:3a, y:3b, z:3c}, {x:3a, y:3b, z:3c}, {x:3a, y:3b, z:3c}]

Ответы [ 3 ]

1 голос
/ 07 февраля 2020

Что не так

my_list.append(my_dict) добавляет ссылку к объекту my_dict к my_list. Поэтому в конце for l oop в вашем примере my_list - это список ссылок на точно такой же словарь в памяти.

Вы можете убедиться в этом сами, используя функцию id. id, по крайней мере, в CPython, в основном дает адрес памяти объекта. Если вы сделаете

article_list.extend(returned_list)
print([id(d) for d in article_list])

, вы получите список идентичных адресов памяти. На моей машине я получаю

[139920570625792, 139920570625792, 139920570625792]

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

Хорошее обсуждение ссылок и объектов в Python можно найти в этом ответе { ссылка }

Исправление

Перемещение определения my_dict внутри for l oop означает, что вы получаете новый отдельный словарь для каждого элемента my_list , Теперь операция обновления не повлияет на другие словари в списке, а my_list - это список ссылок на несколько разных словарей.

def add_entries(list_of_dict):
    keys = ['x','y','z']
    entry_keys = ['ka','kb','kc']

    my_list = []

    for item in list_of_dict:
        #defining a new dictionary here
        my_dict = dict.fromkeys(keys,0)

        # conditionally append the entries into the temporary dictionary maintaining desired key names
        my_dict.update({a: item[b] for a,b in zip(keys, entry_keys) if b in item})
        my_list.append(my_dict)

    return my_list
1 голос
/ 07 февраля 2020

Вы можете использовать это.

keys=['x','y','z']
res=[{k1:d[k]} for d in list_of_dict for k,k1 in zip(d,keys)]

вывод

[{'x': '1a'},
 {'y': '1b'},
 {'z': '1c'},
 {'x': '2a'},
 {'x': '3a'},
 {'y': '3b'},
 {'z': '3c'}]
0 голосов
/ 07 февраля 2020

Попробуйте это:

list_new_d=[]
for d in list_of_dict:
  new_d={}

  for k,v in d.items():
    if k == 'ka':
      new_d['x'] = v

    if k == 'kb':
      new_d['y'] = v

    if k == 'kc':
      new_d['z'] = v
  list_new_d.append(new_d)

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...