Добавление и добавление элементов в список, который содержит словари в качестве элементов - PullRequest
0 голосов
/ 12 июня 2018

Существует список, который содержит словари в качестве своих элементов.Каждый словарь как несколько ключей.Мне нужно добавить значения других ключей на основе заданных значений ключей.например, существует список A:

A =
[{'count': 100, 'price': [100, 200, 300], 'quality': 'good', 'key': 'veg'}, {'count': 150, 'price': [10, 20, 30], 'quality': 'good', 'key': 'non-veg'}, {'count': 200, 'price': [1, 2, 3], 'quality': 'good', 'key': 'veg'}, {'count': 100, 'price': [110, 220, 330], 'quality': 'good', 'key': 'non-veg'}]

Я пытаюсь добавить значения этих элементов на основе значения ключа.Мне нужен вывод, как:

[{'count': 300, 'price': [100, 200, 300, 1, 2, 3], 'quality': 'good', 'key': 'veg'}, {'count': 250, 'price': [10, 20, 30, 110, 220, 330], 'quality': 'good', 'key': 'non-veg'}]

Я пытался использовать функции itertools groupby и map.Но НЕ способен получить результат точно так, как ожидалось.Есть ли простой способ сделать это?

Ответы [ 2 ]

0 голосов
/ 12 июня 2018

Для решения на чистом Python collections.defaultdict, вероятно, лучший вариант.

Если вы хотите использовать стороннюю библиотеку, это возможно через Pandas:

import pandas as pd
import numpy as np

# create dataframe from list of dictionaries
df = pd.DataFrame(A)

print(df)

   count      key            price quality
0    100      veg  [100, 200, 300]    good
1    150  non-veg     [10, 20, 30]    good
2    200      veg        [1, 2, 3]    good
3    100  non-veg  [110, 220, 330]    good

# define aggregation rules
agg_dict = {'price': lambda x: np.array(x.values.tolist()).sum(axis=0).tolist(),
            'count': np.sum,
            'quality': 'first'}

# apply aggregation rules
res = df.groupby('key').agg(agg_dict).reset_index()

print(res)

       key            price  count quality
0  non-veg  [120, 240, 360]    250    good
1      veg  [101, 202, 303]    300    good

Затем для получения словарного результата:

d = res.to_dict(orient='records')

print(d)

[{'key': 'non-veg', 'price': [120, 240, 360], 'count': 250, 'quality': 'good'},
 {'key': 'veg', 'price': [101, 202, 303], 'count': 300, 'quality': 'good'}]
0 голосов
/ 12 июня 2018

Столько, сколько я люблю groupby, я не думаю, что это хорошая идея здесь.Ваши элементы чередуются veg и non-veg, но groupby ожидает, что группы будут смежными, что означает, что это сработает только при первом вызове sorted, после чего вы отбрасываете всю простоту и производительностьПреимущества итеративного выполнения действий.

Между тем, без сортировки будет гораздо проще создать диктовку, основанную на значениях ключей, чем список, который вы должны продолжать искать для каждого ключа.Например:

d = collections.defaultdict(lambda: dict(count=0, price=[], quality=''))
for entry in A:
    key = entry['key']
    target = d[key]
    target['count'] += entry['count']
    target['price'].extend(entry['price'])
    target['quality'] = 'something' # I don't know what your aggregation rule is

Теперь d выглядит следующим образом:

defaultdict(<function __main__.<lambda>>,
            {'non-veg': {'count': 250,
              'price': [10, 20, 30, 110, 220, 330]],
              'quality': 'something'},
             'veg': {'count': 300,
              'price': [100, 200, 300, 1, 2, 3]],
              'quality': 'something'}})

И если вам действительно нужен список в конце, это просто:

[dict(key=key, **value) for key, value in d.items()]

В качестве альтернативы, если структура dict оказывается более полезной, чем список, просто используйте это.(Используйте dict.setdefault вместо defaultdict или d = dict(d) в конце, если вы не хотите, чтобы KeyError s в последующих поисках превратились в значения по умолчанию, конечно.)

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