for i in l:
for k in i:
if k[0]=i[0][0]:
# then I dont know
8 Réponses :
Cette compréhension de liste est assez horrible, mais fait ce que vous recherchez - trouver l'élément minimum basé sur le troisième élément, pour chaque sous-liste avec le premier élément itérant sur un ensemble de premiers éléments.
>>> [min((x for x in l if x[0] == y), key=lambda x: x[2]) for y in set(z[0] for z in l)] [['b', 'random_str2', 5], ['a', 'random_str', 4]]
Regrouper par premier élément, et dans chaque groupe rechercher min par troisième:
f2 = lambda x: x[2] f0 = lambda x: x[0] [min(subl, key=f2) for _, subl in itertools.groupby(sorted(l, key=f0), key=f0)] # => [['a', 'random_str', 4], ['b', 'random_str2', 5]]
Je pense que vous devez trier avant l'utilisation de groupby .
Cela peut être réalisé avec des pandas , un sort_values et un groupby:
[['a', 'random_str', 4], ['b', 'random_str2', 5]]
imprime
import pandas as pd l=[['a', 'random_str', 4], ['b', 'random_str2', 5], ['b', 'random_str3', 7]] #create dataframe from list of list df = pd.DataFrame(l) #sort column based on third column / index = 2 df = df.sort_values(by=2) #groupby first column and only take first entry which is lowest int after sort. df = df.groupby(0).head(1) #put back to list of list df = df.values.tolist() print(df)
Énorme exagération si OP n'utilise pas déjà les pandas dans ce projet
pas si bon / manière pythonique, mais vous pouvez utiliser dictionnaire pour obtenir le résultat
[['a', 'random_str', 4], ['b', 'random_str2', 5]]
sortie
l=[['a', 'random_str', 4], ['b', 'random_str2', 5], ['b', 'random_str3', 7]]
res = {}
for sublist in l:
if sublist[0] not in res.keys():
res.update({sublist[0]:[sublist[1], sublist[2]]})
else:
if sublist[2]<res[sublist[0]][1]:
res[sublist[0]][1] = sublist[2]
final_res = [[index, res[index][0], res[index][1]] for index, value in res.items()]
print(final_res)
cela fonctionne, mais seulement pour comparer deux sous-listes, comment puis-je le changer pour qu'il compare n sous-listes?
Cela devrait faire l'affaire. (Je suis sûr que vous pourriez réduire la complexité du temps avec un algorithme intelligent qui ne trie pas, mais à moins que nous ne parlions d'un goulot d'étranglement ici, vous ne devriez pas trop vous inquiéter à ce sujet.)
>>> from itertools import groupby >>> from operator import itemgetter >>> >>> first, third = itemgetter(0), itemgetter(2) >>> l = [['a', 'random_str', 4], ['b', 'random_str2', 5], ['b', 'random_str3', 7]] >>> >>> groups = groupby(sorted(l), key=first) >>> [min(list(group), key=third) for _, group in groups] [['a', 'random_str', 4], ['b', 'random_str2', 5]]
L'idée est de regrouper vos données par le premier élément de chaque sous-liste. groupby a besoin de l pour être trié pour ce faire. ( sorted trie déjà lexicographiquement, mais vous pouvez l'optimiser en utilisant sorted (l, key = first) de telle sorte que seul le premier élément est pris en compte pour le tri.) Ensuite, nous extraire le minimum de chaque groupe par rapport à l'élément trois (index 2).
Tout cela pourrait être fait en une seule ligne, mais je trouve les oneliners groupby terriblement illisibles, donc je opté pour une solution avec plus de lignes et des noms de variables auto-documentés.
Faire cela via dataframe est selon moi le plus simple et le plus efficace. Essayez
[['a', 'random_str4', 4], ['b', 'random_str2', 5]]
Ceci génère le résultat souhaité, c'est-à-dire
import pandas as pd data = [['a', 'random_str4', 4], ['b', 'random_str2', 5], ['b', 'random_str3', 7], ['a', 'random_str2', 6]] df = pd.DataFrame(data) df = df.sort_values(by = 2) df = df.drop_duplicates(0) df.values.tolist()
Je sais que ce n'est pas la solution la plus faisable, mais cela fonctionne bien pour le moment.
En supposant que la liste est triée par ordre croissant,
l.sort(key=lambda x: x[0])
faites,
print(get_result(l))
si la liste est triée, utilisez ceci avant d'appeler la méthode,
def get_result(l) :
temp_list = []
i = 0
while i < len(l) - 1 :
min = l[i]
while i<len(l)-1 and l[i][0] == l[i+1][0] :
if l[i][2] < l[i+1][2] :
min = l[i]
else :
min = l[i+1]
i += 1
temp_list.append(min)
i += 1
return temp_list
Une autre option peut être celle-ci:
l = [['a', 'random_str', 4], ['b', 'random_str2', 5], ['b', 'random_str3', 7]]
# initialize a dict
d = {x[0]: list() for x in l}
# lambda function to compare values
f = lambda x: x if not d[x[0]] or x[2] < d[x[0]][2] else d[x[0]]
# list comprehension to iterate and process the list of values
[d.update({x[0]: f(x)}) for x in l]
# output exected: [['a', 'random_str', 4], ['b', 'random_str2', 5]]
print(list(d.values()))
cela fonctionne, mais seulement pour comparer deux sous-listes, comment puis-je le changer pour qu'il compare n sous-listes?
Soyez un peu plus précis, donnez un exemple.
l = [['a', 'random_str', 4], ['b', 'random_str2', 5], ['b', 'random_str3', 7], ['b', 'random_str4' , 6], ['b', 'random_str5', 8]] .Donc, dans un exemple comme celui-là, disons que j'ai n nombre de sous-listes avec la chaîne 'b' qui est identique et le problème est que cela va ne comparez toujours que les deux premiers que la boucle trouve. L'idée est que dans cet exemple, il devrait être capable de regarder les quatre sous-listes ci-dessus et de ne conserver que la sous-liste avec la valeur int la plus basse par rapport aux autres. donc la sortie serait [['a', 'random_str', 4], ['b', 'random_str2', 5] I.e supprime les autres sous-listes
Je viens de le vérifier et cela fonctionne correctement, avez-vous de mauvais résultats?
L'entrée est-elle garantie d'être ordonnée par le premier élément?