tuplas - listas por comprensión python
Clasificación y agrupación de listas anidadas en Python (8)
Use una función para reordenar la lista para que pueda agrupar por cada elemento en la lista. Por ejemplo, me gustaría poder agrupar en la segunda columna (para que todos los 21 estén juntos)
Las listas tienen un método de clasificación incorporado y puede proporcionar una función que extraiga la clave de clasificación.
>>> import pprint
>>> l.sort(key = lambda ll: ll[1])
>>> pprint.pprint(l)
[[''4'', ''21'', ''1'', ''14'', ''2008-10-24 15:42:58''],
[''5'', ''21'', ''3'', ''19'', ''2008-10-24 15:45:45''],
[''6'', ''21'', ''1'', ''1somename'', ''2008-10-24 15:45:49''],
[''3'', ''22'', ''4'', ''2somename'', ''2008-10-24 15:22:03''],
[''7'', ''22'', ''3'', ''2somename'', ''2008-10-24 15:45:51'']]
Use una función para mostrar solo ciertos valores de cada lista interna. Por ejemplo, me gustaría reducir esta lista para que solo contenga el 4to valor de campo de ''2somename''
Esto parece un trabajo para las listas de comprensión
>>> [ll[3] for ll in l]
[''14'', ''2somename'', ''19'', ''1somename'', ''2somename'']
Tengo la siguiente estructura de datos (una lista de listas)
[
[''4'', ''21'', ''1'', ''14'', ''2008-10-24 15:42:58''],
[''3'', ''22'', ''4'', ''2somename'', ''2008-10-24 15:22:03''],
[''5'', ''21'', ''3'', ''19'', ''2008-10-24 15:45:45''],
[''6'', ''21'', ''1'', ''1somename'', ''2008-10-24 15:45:49''],
[''7'', ''22'', ''3'', ''2somename'', ''2008-10-24 15:45:51'']
]
Me gustaría poder
Use una función para reordenar la lista para que pueda agrupar por cada elemento en la lista. Por ejemplo, me gustaría poder agrupar en la segunda columna (para que todos los 21 estén juntos)
Use una función para mostrar solo ciertos valores de cada lista interna. Por ejemplo, me gustaría reducir esta lista para que solo contenga el 4to valor de campo de ''2somename''
entonces la lista se vería así
[
[''3'', ''22'', ''4'', ''2somename'', ''2008-10-24 15:22:03''],
[''7'', ''22'', ''3'', ''2somename'', ''2008-10-24 15:45:51'']
]
Para la parte (2), siendo x tu matriz, creo que quieres,
[y for y in x if y[3] == ''2somename'']
Que devolverá una lista de solo sus listas de datos que tienen un cuarto valor siendo ''2somename'' ... Aunque parece que Kamil le está dando el mejor consejo al ir a SQL ...
Si entiendo tu pregunta correctamente, el siguiente código debería hacer el trabajo:
l = [
[''4'', ''21'', ''1'', ''14'', ''2008-10-24 15:42:58''],
[''3'', ''22'', ''4'', ''2somename'', ''2008-10-24 15:22:03''],
[''5'', ''21'', ''3'', ''19'', ''2008-10-24 15:45:45''],
[''6'', ''21'', ''1'', ''1somename'', ''2008-10-24 15:45:49''],
[''7'', ''22'', ''3'', ''2somename'', ''2008-10-24 15:45:51'']
]
def compareField(field):
def c(l1,l2):
return cmp(l1[field], l2[field])
return c
# Use compareField(1) as the ordering criterion, i.e. sort only with
# respect to the 2nd field
l.sort(compareField(1))
for row in l: print row
print
# Select only those sublists for which 4th field==''2somename''
l2somename = [row for row in l if row[3]==''2somename'']
for row in l2somename: print row
Salida:
[''4'', ''21'', ''1'', ''14'', ''2008-10-24 15:42:58'']
[''5'', ''21'', ''3'', ''19'', ''2008-10-24 15:45:45'']
[''6'', ''21'', ''1'', ''1somename'', ''2008-10-24 15:45:49'']
[''3'', ''22'', ''4'', ''2somename'', ''2008-10-24 15:22:03'']
[''7'', ''22'', ''3'', ''2somename'', ''2008-10-24 15:45:51'']
[''3'', ''22'', ''4'', ''2somename'', ''2008-10-24 15:22:03'']
[''7'', ''22'', ''3'', ''2somename'', ''2008-10-24 15:45:51'']
Si lo asignó a var "a" ...
# 1:
a.sort(lambda x,y: cmp(x[1], y[1]))
# 2:
filter(lambda x: x[3]=="2somename", a)
Si va a hacer una gran cantidad de clasificación y filtrado, es posible que desee algunas funciones de ayuda.
m = [
[''4'', ''21'', ''1'', ''14'', ''2008-10-24 15:42:58''],
[''3'', ''22'', ''4'', ''2somename'', ''2008-10-24 15:22:03''],
[''5'', ''21'', ''3'', ''19'', ''2008-10-24 15:45:45''],
[''6'', ''21'', ''1'', ''1somename'', ''2008-10-24 15:45:49''],
[''7'', ''22'', ''3'', ''2somename'', ''2008-10-24 15:45:51'']
]
# Sort and filter helpers.
sort_on = lambda pos: lambda x: x[pos]
filter_on = lambda pos,val: lambda l: l[pos] == val
# Sort by second column
m = sorted(m, key=sort_on(1))
# Filter on 4th column, where value = ''2somename''
m = filter(filter_on(3,''2somename''),m)
Simplemente estás creando índices en tu estructura, ¿verdad?
>>> from collections import defaultdict
>>> def indexOn( things, pos ):
... inx= defaultdict(list)
... for t in things:
... inx[t[pos]].append(t)
... return inx
...
>>> a=[
... [''4'', ''21'', ''1'', ''14'', ''2008-10-24 15:42:58''],
... [''3'', ''22'', ''4'', ''2somename'', ''2008-10-24 15:22:03''],
... [''5'', ''21'', ''3'', ''19'', ''2008-10-24 15:45:45''],
... [''6'', ''21'', ''1'', ''1somename'', ''2008-10-24 15:45:49''],
... [''7'', ''22'', ''3'', ''2somename'', ''2008-10-24 15:45:51'']
... ]
Aquí está su primera solicitud, agrupada por posición 1.
>>> import pprint
>>> pprint.pprint( dict(indexOn(a,1)) )
{''21'': [[''4'', ''21'', ''1'', ''14'', ''2008-10-24 15:42:58''],
[''5'', ''21'', ''3'', ''19'', ''2008-10-24 15:45:45''],
[''6'', ''21'', ''1'', ''1somename'', ''2008-10-24 15:45:49'']],
''22'': [[''3'', ''22'', ''4'', ''2somename'', ''2008-10-24 15:22:03''],
[''7'', ''22'', ''3'', ''2somename'', ''2008-10-24 15:45:51'']]}
Esta es su segunda solicitud, agrupada por posición 3.
>>> dict(indexOn(a,3))
{''19'': [[''5'', ''21'', ''3'', ''19'', ''2008-10-24 15:45:45'']], ''14'': [[''4'', ''21'', ''1'', ''14'', ''2008-10-24 15:42:58'']], ''2somename'': [[''3'', ''22'', ''4'', ''2somename'', ''2008-10-24 15:22:03''], [''7'', ''22'', ''3'', ''2somename'', ''2008-10-24 15:45:51'']], ''1somename'': [[''6'', ''21'', ''1'', ''1somename'', ''2008-10-24 15:45:49'']]}
>>> pprint.pprint(_)
{''14'': [[''4'', ''21'', ''1'', ''14'', ''2008-10-24 15:42:58'']],
''19'': [[''5'', ''21'', ''3'', ''19'', ''2008-10-24 15:45:45'']],
''1somename'': [[''6'', ''21'', ''1'', ''1somename'', ''2008-10-24 15:45:49'']],
''2somename'': [[''3'', ''22'', ''4'', ''2somename'', ''2008-10-24 15:22:03''],
[''7'', ''22'', ''3'', ''2somename'', ''2008-10-24 15:45:51'']]}
Para la primera pregunta, lo primero que debe hacer es ordenar la lista por el segundo campo:
x = [
[''4'', ''21'', ''1'', ''14'', ''2008-10-24 15:42:58''],
[''3'', ''22'', ''4'', ''2somename'', ''2008-10-24 15:22:03''],
[''5'', ''21'', ''3'', ''19'', ''2008-10-24 15:45:45''],
[''6'', ''21'', ''1'', ''1somename'', ''2008-10-24 15:45:49''],
[''7'', ''22'', ''3'', ''2somename'', ''2008-10-24 15:45:51'']
]
from operator import itemgetter
x.sort(key=itemgetter(1))
Entonces puedes usar la función groupby por itertools:
from itertools import groupby
y = groupby(x, itemgetter(1))
Ahora y es un iterador que contiene tuplas de (elemento, iterador de elemento). Es más confuso explicar estas tuplas que mostrar el código:
for elt, items in groupby(x, itemgetter(1)):
print(elt, items)
for i in items:
print(i)
Que impresiones:
21 <itertools._grouper object at 0x511a0>
[''4'', ''21'', ''1'', ''14'', ''2008-10-24 15:42:58'']
[''5'', ''21'', ''3'', ''19'', ''2008-10-24 15:45:45'']
[''6'', ''21'', ''1'', ''1somename'', ''2008-10-24 15:45:49'']
22 <itertools._grouper object at 0x51170>
[''3'', ''22'', ''4'', ''2somename'', ''2008-10-24 15:22:03'']
[''7'', ''22'', ''3'', ''2somename'', ''2008-10-24 15:45:51'']
Para la segunda parte, debes usar las listas de comprensión que ya mencionamos aquí:
from pprint import pprint as pp
pp([y for y in x if y[3] == ''2somename''])
Que impresiones:
[[''3'', ''22'', ''4'', ''2somename'', ''2008-10-24 15:22:03''],
[''7'', ''22'', ''3'', ''2somename'', ''2008-10-24 15:45:51'']]
Se parece mucho a que está tratando de usar una lista como base de datos.
Hoy Python incluye enlaces sqlite en la distribución central. Si no necesita persistencia, es realmente fácil crear una base de datos sqlite en memoria (ver ¿Cómo creo una base de datos en memoria sqllite3? ).
Luego puede usar sentencias de SQL para hacer todo este ordenamiento y filtrado sin tener que reinventar la rueda.