Реструктуризация списка Python Dicts с использованием setdefault - PullRequest
1 голос
/ 15 мая 2019

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

Кроме того, у меня есть лишний список (т.е. мой вывод заканчивается как [[{...}]], а не [{...}].

Я использовал пример здесь:

Как мне сгруппировать этот список диктов к тому же месяцу?

Что приближает меня к тому, чего я хочу, однако я застрял в финалеstage!

market = [
    {'selection_id': 1099, 'value': '11', 'value_name': 'a'},
    {'selection_id': 1099, 'value': '78', 'value_name': 'p'},
    {'selection_id': 1097, 'value': '39', 'value_name': 'b'},
    {'selection_id': 1097, 'value': '52', 'value_name': 'f'},
    {'selection_id': 1098, 'value': '98', 'value_name': 'd'},
    {'selection_id': 1099, 'value': '13', 'value_name': 'y'},
    {'selection_id': 1098, 'value': '4', 'value_name': 'r'},
]

new_structure = {}
new_structure2 = []

for z in market:
        new_structure.setdefault(z['selection_id'], []).append((z['value'], z['value_name']))
        t = [{'selection_id': m, 'value_dict': n} for m, n in new_structure.items()]
new_structure2.append(t)

print(new_structure2)

Это выводит как:

[[{'selection_id': 1099, 'value_dict': [('11', 'a'), ('78', 'p'), ('13',  
 'y')]}, {'selection_id': 1097, 'value_dict': [('39', 'b'), ('52', 'f')]},  
 {'selection_id': 1098, 'value_dict': [('98', 'd'), ('4', 'r')]}]]

Что очень близко, однако я стремлюсь к следующему:

[{'selection_id': 1099,
  'value_dict': [{'value': '11', 'value_name': 'a'},
                 {'value': '78', 'value_name': 'p'},
                 {'value': '13', 'value_name': 'y'}]},
 {'selection_id': 1097,
  'value_dict': [{'value': '39', 'value_name': 'b'},
                 {'value': '52', 'value_name': 'f'}]},
 {'selection_id': 1098,
  'value_dict': [{'value': '98', 'value_name': 'd'},
                 {'value': '4', 'value_name': 'r'}]}]

Я ценю еговозможно, это действительно простое исправление, но оно ускользает от меня на данный момент, поэтому любые рекомендации будут с благодарностью!

Ответы [ 3 ]

3 голосов
/ 15 мая 2019

Вот несколько подсказок:

Первое, что нужно отсортировать по selection_id :

by_selection_id = operator.itemgetter('selection_id')
market.sort(key=by_selection_id)

Затем вы можете группировать по selection_id :

for selection_id, group in itertools.groupby(market, key=by_selection_id):
    print(selection_id, list(group))

Вы получаете:

(1097, [{'value_name': 'b', 'value': '39', 'selection_id': 1097},
        {'value_name': 'f', 'value': '52', 'selection_id': 1097}])
(1098, [{'value_name': 'd', 'value': '98', 'selection_id': 1098},
        {'value_name': 'r', 'value': '4', 'selection_id': 1098}])
(1099, [{'value_name': 'a', 'value': '11', 'selection_id': 1099},
        {'value_name': 'p', 'value': '78', 'selection_id': 1099},
        {'value_name': 'y', 'value': '13', 'selection_id': 1099}])

Тогда легко составить окончательный список.

Вот решение с использованием списка понимания / dict:

new_structure = [{'selection_id': selection_id,
                  'value_dict': [{'value': item['value'],
                                  'value_name': item['value_name']} for item in group]}
                 for selection_id, group in itertools.groupby(market, key=by_selection_id)]

Или используя классический список с append:

new_structure = []
for selection_id, group in itertools.groupby(market, key=by_selection_id):
    value_dict = [{'value': item['value'], 'value_name': item['value_name']} for item in group]
    new_structure.append({'selection_id': selection_id,
                          'value_dict': value_dict})
1 голос
/ 15 мая 2019

Я получаю в итоге то, что похоже на кортеж, а не на диктовку)

Это потому, что вы добавляете кортеж, а не диктат:

.append((z['value'], z['value_name']))
0 голосов
/ 15 мая 2019

Итак, просто для обновления, основываясь на ответе @ Code-Apprentice, я переписал свой код следующим образом:

market = [
    {'selection_id': 1099, 'value': '11', 'value_name': 'a'},
    {'selection_id': 1099, 'value': '78', 'value_name': 'p'},
    {'selection_id': 1097, 'value': '39', 'value_name': 'b'},
    {'selection_id': 1097, 'value': '52', 'value_name': 'f'},
    {'selection_id': 1098, 'value': '98', 'value_name': 'd'},
    {'selection_id': 1099, 'value': '13', 'value_name': 'y'},
    {'selection_id': 1098, 'value': '4', 'value_name': 'r'},
]

new_structure = {}
new_structure2 = []

for z in market:
    new_structure.setdefault(z['selection_id'], []).append({'value': z['value'],
                                                            'value_name': z['value_name']})
    t = [{'selection_id': m, 'value_dict': n} for m, n in new_structure.items()]
    new_structure2.append(t)

print(new_structure2)

Что затем приближает меня к желаемому результату. Единственная оставшаяся проблема - это лишний список (т.е. [[{....}]] вместо [{...}]), я полагаю, что это, вероятно, из-за того, как я написал строку t = ....

Вот мой вывод, я опубликую обновление, как только я избавлюсь от этого дополнительного списка на случай, если ответ будет полезен кому-либо еще (но, пожалуйста, не стесняйтесь, если вы заметите его передо мной):

[[{'selection_id': 1099,
   'value_dict': [{'value': '11', 'value_name': 'a'},
                  {'value': '78', 'value_name': 'p'},
                  {'value': '13', 'value_name': 'y'}]},
  {'selection_id': 1097,
   'value_dict': [{'value': '39', 'value_name': 'b'},
                  {'value': '52', 'value_name': 'f'}]},
  {'selection_id': 1098,
   'value_dict': [{'value': '98', 'value_name': 'd'},
                  {'value': '4', 'value_name': 'r'}]}]]

Так смешно, просто! Я был слишком сложен, просто удалил лишнюю ссылку на список:

market = [
    {'selection_id': 1099, 'value': '11', 'value_name': 'a'},
    {'selection_id': 1099, 'value': '78', 'value_name': 'p'},
    {'selection_id': 1097, 'value': '39', 'value_name': 'b'},
    {'selection_id': 1097, 'value': '52', 'value_name': 'f'},
    {'selection_id': 1098, 'value': '98', 'value_name': 'd'},
    {'selection_id': 1099, 'value': '13', 'value_name': 'y'},
    {'selection_id': 1098, 'value': '4', 'value_name': 'r'},
]

new_structure = {}

for z in market:
    new_structure.setdefault(z['selection_id'], []).append({'value': z['value'],
                                                            'value_name': z['value_name']})

new_structure2 = [{'selection_id': m, 'value_dict': n} for m, n in new_structure.items()]
...