Comment puis-je trouver les doublons dans une liste Python et créer une autre liste des doublons ? La liste ne contient que des entiers.
Réponses
Trop de publicités?D'autres tests. Bien sûr à faire...
set([x for x in l if l.count(x) > 1])
...est trop coûteux. Il est environ 500 fois plus rapide (le tableau le plus long donne de meilleurs résultats) d'utiliser la méthode finale suivante :
def dups_count_dict(l):
d = {}
for item in l:
if item not in d:
d[item] = 0
d[item] += 1
result_d = {key: val for key, val in d.iteritems() if val > 1}
return result_d.keys()
Seulement 2 boucles, pas très coûteux l.count()
opérations.
Voici un code pour comparer les méthodes par exemple. Le code est ci-dessous, voici le résultat :
dups_count: 13.368s # this is a function which uses l.count()
dups_count_dict: 0.014s # this is a final best function (of the 3 functions)
dups_count_counter: 0.024s # collections.Counter
Le code de test :
import numpy as np
from time import time
from collections import Counter
class TimerCounter(object):
def __init__(self):
self._time_sum = 0
def start(self):
self.time = time()
def stop(self):
self._time_sum += time() - self.time
def get_time_sum(self):
return self._time_sum
def dups_count(l):
return set([x for x in l if l.count(x) > 1])
def dups_count_dict(l):
d = {}
for item in l:
if item not in d:
d[item] = 0
d[item] += 1
result_d = {key: val for key, val in d.iteritems() if val > 1}
return result_d.keys()
def dups_counter(l):
counter = Counter(l)
result_d = {key: val for key, val in counter.iteritems() if val > 1}
return result_d.keys()
def gen_array():
np.random.seed(17)
return list(np.random.randint(0, 5000, 10000))
def assert_equal_results(*results):
primary_result = results[0]
other_results = results[1:]
for other_result in other_results:
assert set(primary_result) == set(other_result) and len(primary_result) == len(other_result)
if __name__ == '__main__':
dups_count_time = TimerCounter()
dups_count_dict_time = TimerCounter()
dups_count_counter = TimerCounter()
l = gen_array()
for i in range(3):
dups_count_time.start()
result1 = dups_count(l)
dups_count_time.stop()
dups_count_dict_time.start()
result2 = dups_count_dict(l)
dups_count_dict_time.stop()
dups_count_counter.start()
result3 = dups_counter(l)
dups_count_counter.stop()
assert_equal_results(result1, result2, result3)
print 'dups_count: %.3f' % dups_count_time.get_time_sum()
print 'dups_count_dict: %.3f' % dups_count_dict_time.get_time_sum()
print 'dups_count_counter: %.3f' % dups_count_counter.get_time_sum()
raw_list = [1,2,3,3,4,5,6,6,7,2,3,4,2,3,4,1,3,4,]
clean_list = list(set(raw_list))
duplicated_items = []
for item in raw_list:
try:
clean_list.remove(item)
except ValueError:
duplicated_items.append(item)
print(duplicated_items)
# [3, 6, 2, 3, 4, 2, 3, 4, 1, 3, 4]
Vous supprimez essentiellement les doublons en les convertissant en ensemble ( clean_list
), puis itérer le raw_list
tout en supprimant chaque item
dans la liste propre pour l'occurrence dans raw_list
. Si item
n'est pas trouvée, la question soulevée ValueError
L'exception est attrapée et la item
est ajouté à duplicated_items
liste.
Si l'on a besoin de l'index des éléments dupliqués, il suffit d'utiliser la fonction enumerate
la liste et jouer avec l'index. ( for index, item in enumerate(raw_list):
) qui est plus rapide et optimisé pour les grandes listes (comme des milliers+ d'éléments).
1 votes
Duplicata possible de Comment supprimer les doublons d'une liste en Python tout en préservant l'ordre ?
1 votes
Voulez-vous les duplicata une fois, ou à chaque fois qu'ils sont vus à nouveau ?
0 votes
Je pense que cette question a été traitée avec beaucoup plus d'efficacité ici. stackoverflow.com/a/642919/1748045 L'intersection est une méthode intégrée au jeu et devrait faire exactement ce qui est requis.