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 и в работе со структурами данных как это.
Стараются избегать вложенных структур данных комплекса. Я полагаю, что люди склоняются к 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)
Это очень походит на проблему домашней работы.
Как вышеупомянутый упомянутый плакат, существует несколько более соответствующих структур данных для этого вида данных, некоторый вариант на следующем мог бы быть разумным:
[ ('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)
Я представляю, что было бы проще объединить элементы в List_DICTS во что-то, что выглядит больше похоже на это:
list_dicts2 = [{'id': 1, 'Имя': 'jim' , «Элементы»: [{'itemname': «Карандаш», «Цена»: «0,99 '}], {« ID »: 2,« Имя »:« Мэри »,« предметы »: [{' itemname ': «Книга», «Цена»: «15.49»}, {'itemname': «Ленту», «Цена»: «7,99 '}]]
Вы также можете использовать список кортежей для« предметов »или, возможно, названный кортеж.