2017-02-18 3 views
1

У меня есть словарь, содержащий списки. Например,Группировка списка подписок по некоторым значениям в каждом подсписке

{1: [[sender11, receiver11, text11, address11]], 
2: [[sender21, receiver21, text21, address21], [sender22, receiver22, text22, address22]], 
3: [[sender31, receiver31, text31, address31], [sender32, receiver32, text32, address32], [sender33, receiver33, text33, address33]] 
4: [[sender41, receiver41, text41, address41], [sender42, receiver42, text42, address42], [sender43, receiver43, text43, address43], [sender44, receiver44, text44, address44]]} 

То, что я хочу сделать, это для словаря элементов, которые содержат список с 2-х или более элементов (т.е. dict[2], dict[3] и dict[4] в этом примере), я делаю сравнение sender, receiver, text для каждого значение списка. Для каждой группы значений списка с тем же sender, receiver, text я сделаю что-нибудь.

Так, например, в dict[3], если sender31, receiver31, text31 такие же значения, как и sender32, receiver32, text32sender33, receiver33, text33, то я сделаю что-то со всеми 3 списка значений.

Say в dict[4], если sender41, receiver41, text41 один и то же значение, как sender42, receiver42, text42, в то время как sender43, receiver43, text43 один и то же значение, как sender44, receiver44, text44, но отличается от sender41, receiver41, text41, то я буду работать на этих 2-х группы по отдельности.

Я написал сценарий Python, что довольно много грубой силы сравнивает значения sender21, receiver21, text21 и sender22, receiver22, text22, т.е.

if sender21 == sender22 and receiver21 == receiver22 and text21 == text22: 
    # Do something 

Это не эффективно, как это работает только для 2 списка значений, но я не знаю, как я должен осуществить это таким образом, что он работает для любого числа списка значений больше 1.

ответ

1

Я думаю, defaultdict очевидный путь здесь:

from collections import defaultdict 

def collate(seq): 
    groups = defaultdict(list) 
    for subseq in seq: 
     groups[tuple(subseq[:3])].append(subseq[3]) 
    return groups 

В зависимости от ваших фактических данных вы можете заменить tuple(subseq[:3]) на вышеописанную функцию, например. (subseq[1], subseq[4], subseq[5]), или прилагается subseq[3] с subseq ... это будет зависеть от того, что вы делаете с данными.

Ключ должен быть кортежем, а не списком, поскольку ключи должны быть неизменными.

Пример:

>>> data = [ 
...  ['S1', 'R1', 'T1', 'A3'], 
...  ['S2', 'R2', 'T2', 'A4'], 
...  ['S1', 'R1', 'T1', 'A5'], 
...  ['S2', 'R2', 'T2', 'A6'] 
... ] 

>>> collate(data) 
defaultdict(<type 'list'>, { 
    ('S2', 'R2', 'T2'): ['A4', 'A6'], 
    ('S1', 'R1', 'T1'): ['A3', 'A5'] 
}) 

Вы можете работать с этим так же, как и любой другой словарь, например,

>>> for (sender, receiver, text), addresses in collate(data).items(): 
...  print sender, receiver, text 
...  print '|'.join(addresses) 
...  print 
... 
S2 R2 T2 
A4|A6 

S1 R1 T1 
A3|A5 
  
+0

Спасибо! Это хорошо работает. Однако, если теперь вместо того, чтобы точно соответствовать «(отправитель, получатель, текст)», я хочу, чтобы «(отправитель, получатель, текст)» и «(получатель, отправитель, текст)» были в одной и той же группе, т. Е. порядок отправителя/получателя не имеет значения? Это возможно? Нужно ли мне хешировать? – Rayne

+1

Тип коллекции, который является a) неизменным и b) не заботится о том, что порядок - это «frozenset», поэтому что-то вроде 'groups [frozenset (subseq [: 2]), subseq [2]]. Append (subseq [3]) 'звучит правильно - по мере необходимости. –

+0

Кстати, это то, что вам нужно знать или быть в состоянии быстро узнать из документов, чтобы быть эффективным программистом. Чтение https://docs.python.org/2/library/stdtypes.html снова и снова до тех пор, пока вы просто не узнаете, что стандартные типы возвратят ваши усилия массово в долгосрочной перспективе. –

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