values repeated remove from duplicate python list duplicates rename

repeated - python duplicate



Python: Renombra los duplicados en la lista con nĂºmeros progresivos sin ordenar la lista (6)

Dada una lista como esta:

mylist = ["name", "state", "name", "city", "name", "zip", "zip"]

Me gustaría cambiar el nombre de los duplicados agregando un número para obtener el siguiente resultado:

mylist = ["name1", "state", "name2", "city", "name3", "zip1", "zip2"]

No quiero cambiar el orden de la lista original. Las soluciones sugeridas para esta pregunta relacionada sobre el desbordamiento de pila ordenan la lista, lo que no quiero hacer.


Aquí hay una solución O(n) muy simple. Simplemente recorra la lista almacenando el índice del elemento en la lista. Si hemos visto este elemento anteriormente, use los datos almacenados anteriormente para agregar el valor de ocurrencia.

Este enfoque resuelve el problema con solo crear un diccionario más para mirar hacia atrás. Evita hacer mirar hacia adelante para que no creamos segmentos de listas temporales.

mylist = ["name", "state", "name", "city", "city", "name", "zip", "zip", "name"] dups = {} for i, val in enumerate(mylist): if val not in dups: # Store index of first occurrence and occurrence value dups[val] = [i, 1] else: # Special case for first occurrence if dups[val][1] == 1: mylist[dups[val][0]] += str(dups[val][1]) # Increment occurrence value, index value doesn''t matter anymore dups[val][1] += 1 # Use stored occurrence value mylist[i] += str(dups[val][1]) print mylist # [''name1'', ''state'', ''name2'', ''city1'', ''city2'', ''name3'', ''zip1'', ''zip2'', ''name4'']


Así es como lo haría.

mylist = ["name", "state", "name", "city", "name", "zip", "zip"] from collections import Counter # Counter counts the number of occurrences of each item counts = Counter(mylist) # so we have: {''name'':3, ''state'':1, ''city'':1, ''zip'':2} for s,num in counts.items(): if num > 1: # ignore strings that only appear once for suffix in range(1, num + 1): # suffix starts at 1 and increases by 1 each time mylist[mylist.index(s)] = s + str(suffix) # replace each appearance of s

EDITAR: Aquí está en una sola línea, sin embargo, el orden no se conserva.

[s + str(suffix) if num>1 else s for s,num in Counter(mylist).items() for suffix in range(1, num+1)] # Produces: [''zip1'', ''zip2'', ''city'', ''state'', ''name1'', ''name2'', ''name3'']


Cualquier método en el que se llame a count en cada elemento dará como resultado O(n^2) ya que count es O(n) . Puedes hacer algo como esto:

# not modifying original list from collections import Counter mylist = ["name", "state", "name", "city", "name", "zip", "zip"] counts = {k:v for k,v in Counter(mylist).items() if v > 1} newlist = mylist[:] for i in reversed(range(len(mylist))): item = mylist[i] if item in counts and counts[item]: newlist[i] += str(counts[item]) counts[item]-=1 print(newlist) # [''name1'', ''state'', ''name2'', ''city'', ''name3'', ''zip1'', ''zip2'']

# modifying original list from collections import Counter mylist = ["name", "state", "name", "city", "name", "zip", "zip"] counts = {k:v for k,v in Counter(mylist).items() if v > 1} for i in reversed(range(len(mylist))): item = mylist[i] if item in counts and counts[item]: mylist[i] += str(counts[item]) counts[item]-=1 print(mylist) # [''name1'', ''state'', ''name2'', ''city'', ''name3'', ''zip1'', ''zip2'']

Esto debería ser O(n) .

Otras respuestas proporcionadas:

mylist.index(s) por elemento causa O(n^2)

mylist = ["name", "state", "name", "city", "name", "zip", "zip"] from collections import Counter counts = Counter(mylist) for s,num in counts.items(): if num > 1: for suffix in range(1, num + 1): mylist[mylist.index(s)] = s + str(suffix)

count(x[1]) por elemento causa O(n^2)
También se usa varias veces por elemento junto con el corte de lista.

print map(lambda x: x[1] + str(mylist[:x[0]].count(x[1]) + 1) if mylist.count(x[1]) > 1 else x[1], enumerate(mylist))

Puntos de referencia:

http://nbviewer.ipython.org/gist/dting/c28fb161de7b6287491b


Menos cosas de lujo.

from collections import defaultdict mylist = ["name", "state", "name", "city", "name", "zip", "zip"] finalList = [] dictCount = defaultdict(int) anotherDict = defaultdict(int) for t in mylist: anotherDict[t] += 1 for m in mylist: dictCount[m] += 1 if anotherDict[m] > 1: finalList.append(str(m)+str(dictCount[m])) else: finalList.append(m) print finalList


Mi solución con map y lambda :

print map(lambda x: x[1] + str(mylist[:x[0]].count(x[1]) + 1) if mylist.count(x[1]) > 1 else x[1], enumerate(mylist))

Forma mas tradicional

newlist = [] for i, v in enumerate(mylist): totalcount = mylist.count(v) count = mylist[:i].count(v) newlist.append(v + str(count + 1) if totalcount > 1 else v)

Y el ultimo

[v + str(mylist[:i].count(v) + 1) if mylist.count(v) > 1 else v for i, v in enumerate(mylist)]


Puedes usar la tabla hash para resolver este problema. Definir un diccionario d. clave es la cadena y el valor es (first_time_index_in_the_list, times_of_appearance). Cada vez que vea una palabra, solo verifique el diccionario, y si el valor es 2, use first_time_index_in_the_list para agregar ''1'' al primer elemento, y agregue times_of_appearance al elemento actual. Si es mayor que 2, simplemente agregue times_of_appearance al elemento actual.