2013-10-09 5 views
1

У меня есть список под названием "GO_file":Группировка элементов в списке с помощью питона defaultdic

GO_file = ["A_1 12", "A_2 13", "A_3 14", "A_4 12", "B_1 1", "B_2 1", "B_3 5"] 

Я хочу, чтобы преобразовать его в:

А: 12, 13, 14

B : 1, 5

from collections import defaultdict 
GO_file = ["A_1 12", "A_2 13", "A_3 14", "A_4 12", "B_1 1", "B_2 1" "B_3 5"] 

GO_dict = defaultdict(list) 
for GO_names in GO_file: 
    gene_id = GO_names.split("_")[0] 
    GO_id = GO_names.split(" ")[1:] 
    GO_dict[gene_id] = GO_id 
print GO_dict  

Однако этот код только добавить ключ и только одно значение:

defaultdict(<type 'list'>, {'A': ['12'], 'B': ['5']}) 

Я ценю любые предложения.

ответ

2

Ваш код имеет несколько проблем

  1. Есть дубликаты в вашем GO_ID, и вы, кажется, только заботиться о уникальной. Так что вам нужна defaultdict(set) вместо defaultdict(list)
  2. Вашего раздвоения алгоритм для генерации ключа и значение глючит
  3. GO_dict[gene_id] = GO_id, просто присваивает последнее значение в Словарь вместо добавления его.

Возможное решение исправлена ​​

>>> GO_dict = defaultdict(set) 
>>> for GO_names in GO_file: 
    gene_id,_,GO_id = GO_names.partition(" ") 
    gene_id = gene_id.split("_")[0] 
    GO_dict[gene_id].add(GO_id) 


>>> print GO_dict 
defaultdict(<type 'set'>, {'A': set(['13', '12', '14']), 'B': set(['1', '5'])}) 

Одна из возможных проблем с указанным выше кода, порядок элементов не гарантируется. К сожалению, библиотека по умолчанию не предоставляет OrderedSet, но мы можем легко настроить OrderedDict на сервер нашей цели

>>> GO_dict = defaultdict(OrderedDict) 
>>> for GO_names in GO_file: 
    gene_id,_,GO_id = GO_names.partition(" ") 
    gene_id = gene_id.split("_")[0] 
    GO_dict[gene_id][GO_id] = None 


>>> OrderedDict([('A', ['12', '13', '14']), ('B', ['1', '5'])]) 
OrderedDict([('A', ['12', '13', '14']), ('B', ['1', '5'])]) 

Но

Есть случаи, как этот, я считаю, где itertools решение является более элегантный, чем с использованием defaultdict

>>> from itertools import groupby 
>>> from operator import itemgetter 
>>> GO_file_kv = [(key.split("_")[0], value) 
        for key, value in (elem.split(" ") for elem in GO_file)] 
>>> {key: OrderedDict.fromkeys([e for _, e in value]).keys() 
    for key, value in groupby(sorted(GO_file_kv, key=itemgetter(0)), 
         key=itemgetter(0)) 
} 
{'A': ['12', '13', '14'], 'B': ['1', '5']} 
+0

Спасибо Абхиджит за комплексный ответ! – user690462

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