1
votes

comparaison d'éléments d'une liste de liste et suppression

for i in l:
    for k in i:
        if k[0]=i[0][0]:
            # then I dont know 

1 commentaires

L'entrée est-elle garantie d'être ordonnée par le premier élément?


8 Réponses :


0
votes

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]]


0 commentaires

0
votes

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]]


1 commentaires

Je pense que vous devez trier avant l'utilisation de groupby .



1
votes

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)


1 commentaires

Énorme exagération si OP n'utilise pas déjà les pandas dans ce projet



0
votes

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)


1 commentaires

cela fonctionne, mais seulement pour comparer deux sous-listes, comment puis-je le changer pour qu'il compare n sous-listes?



0
votes

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.


0 commentaires

0
votes

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()


0 commentaires

0
votes

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


0 commentaires

0
votes

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()))


4 commentaires

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?