Как создать новый уровень подсписков на основе общего ключа в каждом подсписке, чтобы классифицировать подсписки?

Как создать новый уровень подсписков на основе общего ключа в каждом подсписке, чтобы классифицировать подсписки? Другими словами, как поместить подсписки в новый подсписок в списке, где все элементы в индексе 1 одинаковы?

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

lsta = [['2014W01','apple',21,'[email protected]'],['2014W02','apple',19,'[email protected]'],['2014W02','banana',51,'[email protected]'],['2014W03','apple',100,'[email protected]'],['2014W01','banana',71,'[email protected]'],['2014W02','organge',21,'[email protected]']]

Я хотел бы, чтобы три подсписка яблок содержались в новом подсписке, а также два подсписка бананов в новом подсписке и т. д.

Desired_List = [[['2014W01','apple',21,'[email protected]'],['2014W02','apple',19,'[email protected]'],['2014W03','apple',100,'[email protected]']],[['2014W02','banana',51,'[email protected]'],['2014W01','banana',71,'[email protected]']],[['2014W02','organge',21,'[email protected]']]]

Бонусные баллы, если бы вы могли сказать мне, как сделать несколько категорий (например, не только разделение по типу фруктов, но и по неделям)?


person Chris    schedule 03.02.2014    source источник
comment
Рассматривали ли вы вместо этого использование диктовок?   -  person sashkello    schedule 03.02.2014
comment
Отличное предложение! Я думаю, что тогда мне следует изменить вопрос на то, как бы я использовал диктовки в этой ситуации.   -  person Chris    schedule 03.02.2014
comment
Связано: stackoverflow.com/questions /409370/   -  person sashkello    schedule 03.02.2014


Ответы (2)


Я возьму немного другую тактику. Вы, вероятно, хотите, чтобы ваше поле группировки было значением поиска в dict. Значение может быть просто list из различных... как бы вы ни называли здесь каждый подсписок. Я назову каждого FruitPerson.

from collections import defaultdict, namedtuple

FruitPerson = namedtuple('FruitPerson','id age email')

d = defaultdict(list)

for sublist in lsta:
    d[sublist[1]].append(FruitPerson(sublist[0],*sublist[2:]))

Тогда, например:

d['apple']
Out[19]: 
[FruitPerson(id='2014W01', age=21, email='[email protected]'),
 FruitPerson(id='2014W02', age=19, email='[email protected]'),
 FruitPerson(id='2014W03', age=100, email='[email protected]')]

d['apple'][0]
Out[20]: FruitPerson(id='2014W01', age=21, email='[email protected]')

d['apple'][0].id
Out[21]: '2014W01'

Изменить: окей, вопрос с множественной категоризацией. Вам просто нужно вложить свои словари. Синтаксис становится немного глупым, потому что аргумент defaultdict должен быть вызываемым; вы можете сделать это с помощью lambda или functools.partial:

FruitPerson = namedtuple('FruitPerson','age email') #just removed 'id' field
d = defaultdict(lambda: defaultdict(list))

for sublist in lsta:
    d[sublist[1]][sublist[0]].append(FruitPerson(*sublist[2:]))

d['apple']
Out[37]: defaultdict(<type 'list'>, {'2014W03': [FruitPerson(age=100, email='[email protected]')], '2014W02': [FruitPerson(age=19, email='[email protected]')], '2014W01': [FruitPerson(age=21, email='[email protected]')]})

d['apple']['2014W01']
Out[38]: [FruitPerson(age=21, email='[email protected]')]

d['apple']['2014W01'][0].email
Out[40]: '[email protected]'

Хотя, честно говоря, на этом этапе вам следует подумать о переходе на настоящую реляционную базу данных, которая может понимать запросы типа SELECT whatever FROM whatever WHERE something.

person roippi    schedule 03.02.2014

Обычно я бы использовал itertools.groupby для этого, но просто для удовольствия, вот метод, который делает всю тяжелую работу вручную

def transform(lista):
    d = {}
    for subl in lista:
        k = subl.pop(1)
        if k not in d:
            d[k] = []
        d[k].append(subl)
    answer = []
    for k, lists in d.items():
        temp = []
        for l in lists:
            l.insert(1, k)
            temp.append(l)
        answer.append(temp)
    return answer

Вывод:

In [56]: transform(lsta)
Out[56]: 
[[['2014W02', 'organge', 21, '[email protected]']],
 [['2014W01', 'apple', 21, '[email protected]'],
  ['2014W02', 'apple', 19, '[email protected]'],
  ['2014W03', 'apple', 100, '[email protected]']],
 [['2014W02', 'banana', 51, '[email protected]'],
  ['2014W01', 'banana', 71, '[email protected]']]]
person inspectorG4dget    schedule 03.02.2014