J’avais besoin de grouper les éléments d’une liste selon certains critères. Par exemple, mettons que j’ai une liste d’objets qui ont comme attributs “name”, “age”, et “city” (plus d’autres trucs) ; j’ai envie de récupérer un dico qui soit “trié” selon ces trois critères ; par exemple pour avoir :
{
'sam' : { # tous les "sam"
5: { # qui ont 5 ans
'Paris': [ , ], #qui habitent Paris
'Nantes': [, ]
},
7: { #tous les sams qui ont 7 ans
'Paris' : [object5],
'Tokyo': [object6, object7] # qui habitent Tokyo
}
}
J’ai donc créé une classe qui s’utilise de la manière suivante:
# on définit nos clefs de tri
key_name = lambda x: x.name
key_age = lambda x: x.age
key_city = lambda x: x.city
# objects contient tous les objets que je veux ordonner
organized_dico = Organizer(objects, (f1, f2, f3))
# on peut classer selon la vile d'abord si on veut:
organized_dico2 = Organizer(objects, (f3, f1, f2))
Et voici le code de la classe, en gros il s’agit d’un defaultdict “récursif” dont tous les niveaux sont eux même des defaultdict et le dernier est une liste. À chaque ajout d’un élément, on évalue successivement les différents sort_keys pour savoir où placer cet élément dans la structure :
from collections import defaultdict
class Organizer(defaultdict):
def __init__(self, iterable=tuple(), sort_keys=tuple()):
super(Organizer, self).__init__(Organizer)
self.sort_keys = sort_keys
self.update(iterable)
def update(self, iterable):
for item in iterable:
current_dict = self
for key in self.sort_keys[:-1]:
current_dict = current_dict[key(item)]
slot = current_dict[self.sort_keys[-1](item)]
if slot:
slot.append(item)
else:
current_dict[self.sort_keys[-1](item)] = [item]
Je ne suis pas pleinement satisfait par ma gestion du dernier niveau de récursion… Des idées pour faire un truc plus clean ?
]]>Artículo sobresaliendo como de costumbre ;)
]]>Me has mordido!
Acabo de notar al leer el artículo, al parecer, el Tío @Sam aún no ha actualizado .
PS : Bueno, yo entiendo su reactividad , es 02 a.m. a Francia
]]>
>>> c = Counter("aabbbbbbbbbbbbcccc")
>>> c & Counter('aaaaaaaaaaaaaaabbcddddddd') # valeurs min
Counter({'b': 2, 'a': 2, 'c': 1})
>>> c | Counter('aaaaaaaaaaaaaaabbcddddddd') # valeurs max
Counter({'a': 15, 'b': 12, 'd': 7, 'c': 4})
UN petit soucis d’encodage non ? (et une petite typo en prime)
]]>