¿Cómo agrupar una lista de tuplas / objetos por índice / atributo similar en python?

Dada una lista

old_list = [obj_1, obj_2, obj_3, ...] 

Quiero crear una lista:

 new_list = [[obj_1, obj_2], [obj_3], ...] 

donde obj_1.some_attr == obj_2.some_attr .

Podría lanzar algunos for bucles y hacer cheques juntos, pero esto es feo. ¿Hay una forma pythonica para esto? por cierto, los atributos de los objetos son todas las cadenas.

Alternativamente, también se aprecia una solución para una lista que contenga tuplas (de la misma longitud) en lugar de objetos.

defaultdict es cómo se hace esto.

Mientras que for bucles son en gran medida esenciales, if declaraciones no lo son.

 from collections import defaultdict groups = defaultdict(list) for obj in old_list: groups[obj.some_attr].append(obj) new_list = groups.values() 

Aquí hay dos casos. Ambos requieren las siguientes importaciones:

 import itertools import operator 

Utilizará itertools.groupby y operator.attrgetter o operator.itemgetter .

Para una situación en la que está agrupando por obj_1.some_attr == obj_2.some_attr :

 get_attr = operator.attrgetter('some_attr') new_list = [list(g) for k, g in itertools.groupby(sorted(old_list, key=get_attr), get_attr)] 

Para a[some_index] == b[some_index] :

 get_item = operator.itemgetter(some_index) new_list = [list(g) for k, g in itertools.groupby(sorted(old_list, key=get_item), get_item)] 

Tenga en cuenta que necesita la ordenación porque itertools.groupby un nuevo grupo cuando cambia el valor de la clave.


Tenga en cuenta que puede usar esto para crear un dict como la respuesta de S.Lott, pero no tiene que usar collections.defaultdict .

Usar un diccionario de comprensión (solo funciona con Python 3+ y posiblemente Python 2.7 pero no estoy seguro):

 groupdict = {k: g for k, g in itertools.groupby(sorted_list, keyfunction)} 

Para versiones anteriores de Python, o como una alternativa más sucinta:

 groupdict = dict(itertools.groupby(sorted_list, keyfunction)) 

Creo que también puedes intentar usar itertools.groupby . Tenga en cuenta que el código a continuación es solo una muestra y debe modificarse de acuerdo con sus necesidades:

 data = [[1,2,3],[3,2,3],[1,1,1],[7,8,9],[7,7,9]] from itertools import groupby # for example if you need to get data grouped by each third element you can use the following code res = [list(v) for l,v in groupby(sorted(data, key=lambda x:x[2]), lambda x: x[2])]# use third element for grouping