2015-03-17 5 views
1

В настоящее время я просматриваю таблицу со следующей структурой.Создать список для каждого уникального значения

uid | action 
1 | A1 
1 | A1 
1 | A1 
1 | A4 
2 | A1 
2 | A8 
2 | A9 
3 | A3 
3 | A7 

Я пытаюсь создать многомерный массив со следующей структурой.

[[A1, A1, A1, A4], [A1, A8, A9], [A3, A7]] 

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

Я придумал несколько раздутое и неправильное решение, используя itertools.groupby(), но я не удовлетворен этим и ищу что-то более простое. Однако я передумал эту проблему и придумываю более сложные решения.

Любые советы будут оценены.

Код:

data = [] 
for i, j in itertools.groupby(table, key=lambda x: x['uid']): 
    event_array = [] 
    for k in list(j): 
     event_array.append(k['action']) 
    data.append([i, event_array]) 
+2

Если последовательность уже отсортирован, 'itertools.groupby' был бы одним из лучших вариантов здесь. – thefourtheye

+0

Каков формат таблицы? Последовательность двух кортежей, представляющих строки? Словарь? – brianmearns

+0

@ sh1ftst0rm словарь. – Black

ответ

3

Согласно OP's comment,

@Black уверен, что данные упорядочены ли вы?

... @thefourtheye, да уверен, как я должен был написать это в SQL перед чтением в питона

Поскольку данные уже упорядочены, например, как этот

>>> data = [{'action': 'A1', 'uid': 1}, 
... {'action': 'A1', 'uid': 1}, 
... {'action': 'A1', 'uid': 1}, 
... {'action': 'A4', 'uid': 1}, 
... {'action': 'A1', 'uid': 2}, 
... {'action': 'A8', 'uid': 2}, 
... {'action': 'A9', 'uid': 2}, 
... {'action': 'A3', 'uid': 3}, 
... {'action': 'A7', 'uid': 3}] 

вы можете просто использовать groupby себя, с вложенным списком понимания, как этот

>>> [[k['action'] for k in j] for i, j in groupby(data, key=lambda x: x['uid'])] 
[['A1', 'A1', 'A1', 'A4'], ['A1', 'A8', 'A9'], ['A3', 'A7']] 
2

Вы можете использовать старый добрый defaultdict:

from collections import defaultdict 

DATA = [{'uid': uid, 'action': action} 
     for uid, action in [(1, 'A1'), 
          (1, 'A1'), 
          (1, 'A1'), 
          (1, 'A4'), 
          (2, 'A1'), 
          (2, 'A8'), 
          (2, 'A9'), 
          (3, 'A3'), 
          (3, 'A7'),]] 

d = defaultdict(list) 

for data in DATA: 
    d[data['uid']].append(data['action']) 

print(d.values()) 

Результат будет:

[['A1', 'A1', 'A1', 'A4'], ['A1', 'A8', 'A9'], ['A3', 'A7']] 
+0

теперь просто закончите с 'd.values ​​()' –

+0

Какой выбор, если данные * не были * сгруппированы уже. –

1

Это должно работать, но похоже groupby уже совершенно хорошо.

uids = {} 
for row in table: 
    uids.setdefault(row['uid'], []).append(row['action']) 

data = [uids[uid] for uid in sorted(uids.keys())] 

Раствор просто итерацию по каждой строке в table, и гарантирует, что существует список для соответствующего UID в uids Dict (с использованием setdefault). Затем он добавляет действие для этой строки в список.

Таким образом, uids будет словарем, ключи которого являются UID, а значения представляют собой последовательности соответствующих действий из таблицы.

Если вы действительно хотите список списков («многомерный массив»), последняя строка использует представление списка для создания списка, элементами которого являются списки действий, хранящихся в файле uids, заказанных uid.

+1

'dict.setdefault' - это старый стиль Python, предварительно датированный доступностью' defaultdict'. Это неоптимально для 'defaultdict', поскольку для каждого вызова он должен построить аргумент just-in-case-the-key-is-missing. Напротив, 'defaultdict (list)' инициализирует defaultdict с помощью фабричного метода, который нужно вызвать только при необходимости. Если вы не стремились к совместимости со старыми версиями Python, используйте новые идиомы. – PaulMcG

+0

@PaulMcGuire, очень приятно, спасибо за информацию! – brianmearns

Смежные вопросы