Python - разделение списка списков на группы - PullRequest
2 голосов
/ 12 февраля 2011

Рассмотрим следующий упрощенный случай:

lol = [['John','Polak',5,3,7,9],
       ['John','Polak',7,9,2,3],
       ['Mark','Eden' ,0,3,3,1],
       ['Mark','Eden' ,5,1,2,9]]

Каким был бы питон и память + экономичный способ преобразования этого списка в список списков-of-списков на основе первых двух параметров:

lolol = [[['John','Polak',5,3,7,9],
          ['John','Polak',7,9,2,3]],
         [['Mark','Eden' ,0,3,3,1],
          ['Mark','Eden' ,5,1,2,9]]]

На самом деле - любая другая структура данных также будет в порядке, если у меня есть правильная иерархия.Например, на ум приходит следующая словарная структура, но ее создание кажется недостаточно эффективным, быстродействующим, и объем памяти, вероятно, будет выше, чем у решения lolol.

dolol = {('John','Polak'):[[5,3,7,9],[7,9,2,3]],
         ('Mark','Eden') :[[0,3,3,1],[5,1,2,9]]}

Ответы [ 3 ]

6 голосов
/ 13 февраля 2011

Список:

from itertools import groupby
lolol = [list(grp) for (match, grp) in groupby(lol, lambda lst: lst[:2])]
# [[['John', 'Polak', 5, 3, 7, 9], ['John', 'Polak', 7, 9, 2, 3]],
#  [['Mark', 'Eden', 0, 3, 3, 1], ['Mark', 'Eden', 5, 1, 2, 9]]]

Словарь:

dolol = dict((tuple(match), [x[2:] for x in grp]) for (match, grp) in 
             groupby(lol, lambda lst: lst[:2]))
# {('John', 'Polak'): [[5, 3, 7, 9], [7, 9, 2, 3]],
#  ('Mark', 'Eden'): [[0, 3, 3, 1], [5, 1, 2, 9]]}

Поскольку itertools.groupby работает с последовательными совпадениями, предполагается сортированный ввод (lol).

5 голосов
/ 12 февраля 2011

Если словарь приемлем, этот код создаст его:

import collections
d = collections.defaultdict(list)
for name, surname, *stuff in lol:
    d[name, surname].append(nums)

Обратите внимание, что для этого требуется Python 3 ( расширенная повторяемая распаковка ).Для Python 2 используйте

for x in lol:
    name = x[0]
    surname = x[1]
    stuff = x[2:]

. Вы можете сложить переменные для сохранения строк.

0 голосов
/ 13 февраля 2011

Чтобы дополнить ответ Делнана эквивалентом Python 2:

from collections import defaultdict

dolol=defaultdict(list)
for data in lol:
    dolol[data[0],data[1]].append(data[2:])
...