2009-12-17 10 views
21

Tengo una lista con los elementos duplicados:¿Cómo encontrar elementos duplicados en una matriz usando for loop en Python?

list_a=[1,2,3,5,6,7,5,2] 

tmp=[] 

for i in list_a: 
    if tmp.__contains__(i): 
     print i 
    else: 
     tmp.append(i) 

He utilizado el código de arriba para encontrar los elementos duplicados en la list_a. No quiero eliminar los elementos de la lista.

Pero quiero usar for loop aquí. Normalmente C/C++ que utilizamos como esto supongo:

for (int i=0;i<=list_a.length;i++) 
    for (int j=i+1;j<=list_a.length;j++) 
     if (list_a[i]==list_a[j]) 
      print list_a[i] 

¿Cómo utilizamos como esto en Python?

for i in list_a: 
    for j in list_a[1:]: 
    .... 

He intentado con el código anterior. Pero se equivoca la solución. No sé cómo aumentar el valor de j.

Respuesta

24

Utilice el operador in en lugar de llamar directamente al __contains__.

Lo que casi tiene obras (pero es O (n ** 2)):

for i in xrange(len(list_a)): 
    for j in xrange(i + 1, len(list_a)): 
    if list_a[i] == list_a[j]: 
     print "duplicate:", list_a[i] 

Pero es mucho más fácil de usar un conjunto (más o menos O (n), debido a la tabla hash):

seen = set() 
for n in list_a: 
    if n in seen: 
    print "duplicate:", n 
    else: 
    seen.add(n) 

O un diccionario, si desea realizar un seguimiento de la ubicación de los duplicados (también O (n)):

import collections 
items = collections.defaultdict(list) 
for i, item in enumerate(list_a): 
    items[item].append(i) 
for item, locs in items.iteritems(): 
    if len(locs) > 1: 
    print "duplicates of", item, "at", locs 

O incluso detectar un duplicado en algún lugar (también O (n)):

if len(set(list_a)) != len(list_a): 
    print "duplicate" 
+0

Por qué la downvote? –

3

Si usted está buscando uno-a-uno entre sus bucles anidados y Python, esto es lo que quiere:

n = len(list_a) 
for i in range(n): 
    for j in range(i+1, n): 
     if list_a[i] == list_a[j]: 
      print list_a[i] 

El código anterior no es "Pythonic". Lo haría algo como esto:

seen = set() 
for i in list_a: 
    if i in seen: 
     print i 
    else: 
     seen.add(i) 

Además, no utilizan __contains__, más bien, utilizar in (como el anterior).

0

Podrías simplemente "traducirlo" línea por línea.

C++

for (int i=0;i<=list_a.length;i++) 
    for (int j=i+1;j<=list_a.length;j++) 
     if (list_a[i]==list_a[j]) 
      print list_a[i] 

Python

for i in range(0, len(list_a)): 
    for j in range(i + 1, len(list_a)) 
     if list_a[i] == list_a[j]: 
      print list_a[i] 

C++ bucle for:

for(int x = start; x < end; ++x) 

Python equivalente:

for x in range(start, end): 
+3

No debe aceptar esta respuesta. Sí, es un código válido, pero no es la forma en que debe codificar en Python. No codifique Python como C/C++ o Java. No son los mismos idiomas, y no están destinados a ser utilizados de la misma manera. –

+0

Estoy de acuerdo con e-satis, aunque la pregunta específicamente intenta comparar la rutina con C/C++, debemos tratar de empujarlo en la dirección correcta. – Mizipzor

16

siempre se puede utilizar una lista de comprensión:

dups = [x for x in list_a if list_a.count(x) > 1] 
+3

Esto recorre la lista una vez para cada elemento (aunque, el código de OP es O (N ** 2) también). –

+0

+1 por one-liner – Mizipzor

+0

Sí, entendí que es ineficiente. Si el OP está buscando eso, debería ir con las respuestas de Roger seguro. –

2

A continuación se requiere que los elementos de la lista para ser hashable (no sólo la implementación de __eq__). lo encuentro más Pythonic utilizar un defaultdict (y tiene el número de repeticiones de forma gratuita):

 
import collections 
l = [1, 2, 4, 1, 3, 3] 
d = collections.defaultdict(int) 
for x in l: 
    d[x] += 1 
print [k for k, v in d.iteritems() if v > 1] 
# prints [1, 3] 
+0

Cambie a 'if d [v]> 1' y voy a +1. –

+0

Chris: Creo que has entendido mal esta respuesta, funciona como está ahora y tu sugerencia la rompería. –

56

Sólo a título informativo, en Python 2.7+, podemos utilizar Contador

import collections 

x=[1, 2, 3, 5, 6, 7, 5, 2] 

>>> x 
[1, 2, 3, 5, 6, 7, 5, 2] 

>>> y=collections.Counter(x) 
>>> y 
Counter({2: 2, 5: 2, 1: 1, 3: 1, 6: 1, 7: 1}) 

único lista

>>> list(y) 
[1, 2, 3, 5, 6, 7] 

artículos encontraron más de 1 vez

>>> [i for i in y if y[i]>1] 
[2, 5] 

artículos encontraron sólo una vez

>>> [i for i in y if y[i]==1] 
[1, 3, 6, 7] 
+0

+1, definitivamente pitónico. – LeMiz

+2

'[n para n, i en y.iteritems() si i> 1]' en su lugar, y 'i == 1'. –

+0

... pero ¿por qué la lista (y) no es mostrable? – LeMiz

-2

aplicación un poco más Pythonic (no la mayoría, por supuesto), sino en el espíritu de su código C podrían ser:

for i, elem in enumerate(seq): 
    if elem in seq[i+1:]: 
     print elem 

Editar : sí, imprime los elementos más de una vez si hay más de 2 repeticiones, pero eso es lo que hace el pseudocódigo C de la operadora también.

+0

Debe ordenar antes de hacerlo. Usar ordenadoAdemás, imprimirá el mismo duplicado varias veces si hay más de uno igual. –

+0

Esto imprimirá el mismo elemento varias veces si ocurre más de 2 veces en la lista. – truppo

+1

¿Se han molestado en leer el código de la operación? Hace exactamente lo mismo. @ e-satis No hay necesidad de ordenar, quizás quisiste decir algo como '[k para k, it en itertools.groupby (ordenado (l)) si len (list (it))> 1]'? – fortran

7

Antes de Python 2.3, el uso dict():

>>> lst = [1, 2, 3, 5, 6, 7, 5, 2] 
>>> stats = {} 
>>> for x in lst : # count occurrences of each letter: 
...  stats[x] = stats.get(x, 0) + 1 
>>> print stats 
{1: 1, 2: 2, 3: 1, 5: 2, 6: 1, 7: 1} # filter letters appearing more than once: 
>>> duplicates = [dup for (dup, i) in stats.items() if i > 1] 
>>> print duplicates 

lo tanto una función:

def getDuplicates(iterable): 
    """ 
     Take an iterable and return a generator yielding its duplicate items. 
     Items must be hashable. 

     e.g : 

     >>> sorted(list(getDuplicates([1, 2, 3, 5, 6, 7, 5, 2]))) 
     [2, 5] 
    """ 
    stats = {} 
    for x in iterable : 
     stats[x] = stats.get(x, 0) + 1 
    return (dup for (dup, i) in stats.items() if i > 1) 

con Python 2.3 está configurado(), y es incluso un built-in después de que:

def getDuplicates(iterable): 
    """ 
     Take an iterable and return a generator yielding its duplicate items. 
     Items must be hashable. 

     e.g : 

     >>> sorted(list(getDuplicates([1, 2, 3, 5, 6, 7, 5, 2]))) 
     [2, 5] 
    """ 
    try: # try using built-in set 
     found = set() 
    except NameError: # fallback on the sets module 
     from sets import Set 
     found = Set() 

    for x in iterable: 
     if x in found : # set is a collection that can't contain duplicate 
      yield x 
     found.add(x) # duplicate won't be added anyway 

con Python 2.7 y superiores, usted tiene la providi collections módulo endo la misma función que el dict una, y podemos hacerlo más corto (y más rápido, probablemente C bajo el capó) de una solución 1:

import collections 

def getDuplicates(iterable): 
    """ 
     Take an iterable and return a generator yielding its duplicate items. 
     Items must be hashable. 

     e.g : 

     >>> sorted(list(getDuplicates([1, 2, 3, 5, 6, 7, 5, 2]))) 
     [2, 5] 
    """ 
    return (dup for (dup, i) in collections.counter(iterable).items() if i > 1) 

me quedo con la solución 2.

0

Usando numpy:

import numpy as np 
count,value = np.histogram(list_a,bins=np.hstack((np.unique(list_a),np.inf))) 
print 'duplicate value(s) in list_a: ' + ', '.join([str(v) for v in value[count>1]]) 
5
def get_duplicates(arr): 
    dup_arr = arr[:] 
    for i in set(arr): 
     dup_arr.remove(i)  
    return list(set(dup_arr)) 


print get_duplicates([1,2,3,5,6,7,5,2]) 
[2, 5] 

print get_duplicates([1,2,1,3,4,5,4,4,6,7,8,2]) 
[1, 2, 4] 
1

Parece que usted tiene una lista (list_a) incluyendo potencialmente duplicados, que prefiere mantenerlo como es, y crear una lista tmp de-duplicado sobre la base de list_a. En Python 2.7, se puede lograr esto con una línea:

tmp = list(set(list_a))

Al comparar las longitudes de tmp y list_a en este punto debe aclarar si efectivamente existían elementos duplicados en list_a. Esto puede ayudar a simplificar las cosas si desea entrar en el ciclo para un procesamiento adicional.

0

Sólo rápida y sucia,

list_a=[1,2,3,5,6,7,5,2] 
holding_list=[] 

for x in list_a: 
    if x in holding_list: 
     pass 
    else: 
     holding_list.append(x) 

print holding_list 

de salida [1, 2, 3, 5, 6, 7]

2

Usando sólo itertools, y funciona bien en Python 2,5

from itertools import groupby 
list_a = sorted([1, 2, 3, 5, 6, 7, 5, 2]) 
result = dict([(r, len(list(grp))) for r, grp in groupby(list_a)]) 

Resultado:

{1: 1, 2: 2, 3: 1, 5: 2, 6: 1, 7: 1} 
0

En el caso de Py thon3 y si dos listas

def removedup(List1,List2): 
    List1_copy = List1[:] 
     for i in List1_copy: 
      if i in List2: 
       List1.remove(i) 

List1 = [4,5,6,7] 
List2 = [6,7,8,9] 
removedup(List1,List2) 
print (List1) 
0

Por supuesto, no he hecho pruebas, pero supongo que va a ser difícil de superar en velocidad pandas:

pd.DataFrame(list_a, columns=["x"]).groupby('x').size().to_dict() 
Cuestiones relacionadas