список Python dicts, как объединить key:value, где значения - то же?

Python newb, здесь ища некоторую помощь...

Поскольку переменное количество dicts в Python перечисляет как:

list_dicts = [
{'id':'001', 'name':'jim', 'item':'pencil', 'price':'0.99'},
{'id':'002', 'name':'mary', 'item':'book', 'price':'15.49'},
{'id':'002', 'name':'mary', 'item':'tape', 'price':'7.99'},
{'id':'003', 'name':'john', 'item':'pen', 'price':'3.49'},
{'id':'003', 'name':'john', 'item':'stapler', 'price':'9.49'},
{'id':'003', 'name':'john', 'item':'scissors', 'price':'12.99'},
]

Я пытаюсь найти лучший способ сгруппировать dicts, где значение ключевого "идентификатора" равно, затем добавьте/объедините любой уникальный key:value и создайте новый список dicts как:

list_dicts2 = [
{'id':'001', 'name':'jim', 'item1':'pencil', 'price1':'0.99'},
{'id':'002', 'name':'mary', 'item1':'book', 'price1':'15.49', 'item2':'tape', 'price2':'7.99'},
{'id':'003', 'name':'john', 'item1':'pen', 'price1':'3.49', 'item2':'stapler', 'price2':'9.49', 'item3':'scissors', 'price3':'12.99'},
]

До сих пор я выяснил, как сгруппировать dicts в списке с:

myList = itertools.groupby(list_dicts, operator.itemgetter('id'))

Но я борюсь с тем, как создать новый список dicts к:

1) Добавьте дополнительные ключи и значения к первому dict экземпляру, который имеет тот же "идентификатор"

2) Определите новое имя для ключей "объекта" и "цены" (например, "item1", "item2", "item3"). Это кажется неуклюжим мне, есть ли лучший путь?

3) Цикл по каждому "идентификатору" соответствует для создания строки для более позднего вывода

Я принял решение возвратить новый список dicts только из-за удобства передачи dict к функции шаблонной обработки, где установка переменных описательным ключом полезна (существуют многие Вар). Если бы существует более чистый более краткий способ выполнить это, мне было бы любопытно учиться. Снова, я довольно плохо знаком с Python и в работе со структурами данных как это.

9
задан abrg 14 January 2010 в 21:15
поделиться

3 ответа

Стараются избегать вложенных структур данных комплекса. Я полагаю, что люди склоняются к grok их только, в то время как они интенсивно используют структуру данных. После программа закончена или обойдена некоторое время, структура данных быстро становится мистифицирующим.

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

class Item(object):
    def __init__(self,name,price):
        self.name=name
        self.price=price

Точно так же человек, кажется, имеет идентификационное и название и ряд имущества:

class Person(object):
    def __init__(self,id,name,*items):
        self.id=id
        self.name=name
        self.items=set(items)

, Если вы вложились в идею использовать классы как они, затем ваш , list_dicts мог стать

list_people = [
    Person('001','jim',Item('pencil',0.99)),
    Person('002','mary',Item('book',15.49)),
    Person('002','mary',Item('tape',7.99)),
    Person('003','john',Item('pen',3.49)),
    Person('003','john',Item('stapler',9.49)),
    Person('003','john',Item('scissors',12.99)), 
]

Затем для слияния людей на основе идентификатор , вы могли использовать Python , уменьшают функция, наряду с take_items, который берет (объединяет) предметы от одного человека и дает их другому:

def take_items(person,other):
    '''
    person takes other's items.
    Note however, that although person may be altered, other remains the same --
    other does not lose its items.    
    '''
    person.items.update(other.items)
    return person

Соединение всего этого:

import itertools
import operator

class Item(object):
    def __init__(self,name,price):
        self.name=name
        self.price=price
    def __str__(self):
        return '{0} {1}'.format(self.name,self.price)

class Person(object):
    def __init__(self,id,name,*items):
        self.id=id
        self.name=name
        self.items=set(items)
    def __str__(self):
        return '{0} {1}: {2}'.format(self.id,self.name,map(str,self.items))

list_people = [
    Person('001','jim',Item('pencil',0.99)),
    Person('002','mary',Item('book',15.49)),
    Person('002','mary',Item('tape',7.99)),
    Person('003','john',Item('pen',3.49)),
    Person('003','john',Item('stapler',9.49)),
    Person('003','john',Item('scissors',12.99)), 
]

def take_items(person,other):
    '''
    person takes other's items.
    Note however, that although person may be altered, other remains the same --
    other does not lose its items.    
    '''
    person.items.update(other.items)
    return person

list_people2 = [reduce(take_items,g)
                for k,g in itertools.groupby(list_people, lambda person: person.id)]
for person in list_people2:
    print(person)
9
ответ дан 4 December 2019 в 21:49
поделиться

Это очень походит на проблему домашней работы.

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

[ ('001', 'jim', [('pencil', '0.99')]), 
('002', 'mary', [('book', '15.49'), ('tape', '7.99')]), 
('003', 'john', [('pen', '3.49'), ('stapler', '9.49'), ('scissors', '12.99')])]

Это может быть сделано с относительно простым:

list2 = []
for id,iter in itertools.groupby(list_dicts,operator.itemgetter('id')):
  idList = list(iter)
  list2.append((id,idList[0]['name'],[(z['item'],z['price']) for z in idList]))

интересной вещью об этом вопросе является трудность при извлечении 'имени' при использовании groupby, не выполняя итерации мимо предмета.

Для возвращения к исходной цели, хотя, вы могли использовать код как это (как предложенный OP):

list3 = []
for id,name,itemList in list2:
    newitem = dict({'id':id,'name':name})
    for index,items in enumerate(itemList):
        newitem['item'+str(index+1)] = items[0]
        newitem['price'+str(index+1)] = items[1]
    list3.append(newitem)
0
ответ дан 4 December 2019 в 21:49
поделиться

Я представляю, что было бы проще объединить элементы в List_DICTS во что-то, что выглядит больше похоже на это:

list_dicts2 = [{'id': 1, 'Имя': 'jim' , «Элементы»: [{'itemname': «Карандаш», «Цена»: «0,99 '}], {« ID »: 2,« Имя »:« Мэри »,« предметы »: [{' itemname ': «Книга», «Цена»: «15.49»}, {'itemname': «Ленту», «Цена»: «7,99 '}]]

Вы также можете использовать список кортежей для« предметов »или, возможно, названный кортеж.

0
ответ дан 4 December 2019 в 21:49
поделиться
Другие вопросы по тегам:

Похожие вопросы: