Tengo una lista con n elementos:
['pea', 'rpai', 'rpai', 'schiai', 'pea', 'rpe', 'zoi', 'zoi', 'briai', 'rpe']Tengo que asignar un número a cada cadena, cero al principio, y luego incrementar en uno si el elemento es diferente, en lugar de dar el mismo número si el elemento se repite. Ejemplo:
['pea', 'rpai', 'rpai', 'schiai', 'pea', 'rpe', 'zoi', 'zoi', 'briai', 'rpe'] [ 0, 1, 1, 2, 0, 3, 4, 4, 5, 3 ]¿Cómo puedo hacerlo?
Prueba esto:
a = ['pea', 'rpai', 'rpai', 'schiai', 'pea', 'rpe', 'zoi', 'zoi', 'briai', 'rpe'] dct = {} counter = 0 for i in range(len(a)): if a[i] not in dct.keys(): dct[a[i]] = counter counter += 1 print([(i, dct[i]) for i in a])Solo necesitas probar si ya lo tenías
def counts(final): count3 = [] # contains all objects that were already found count2=[] count=0 for x in final: if x not in count3: # test if it's not already in count3 count+=1 count2.append(count) count3.append(x) else: count2.append(count) return count2usar un diccionario lograría esto.
def counts(a): dis = {} count=0 for i in range(len(a)): if a[i] not in dis.keys(): dis[a[i]] = count count+=1 return([dis[x] for x in a])Con un dictado de ayuda:
>>> [*map({k: v for v, k in enumerate(dict.fromkeys(final))}.get, final)] [0, 1, 1, 2, 0, 3, 4, 4, 5, 3]De otra manera:
>>> d = {} >>> [d.setdefault(x, len(d)) for x in final] [0, 1, 1, 2, 0, 3, 4, 4, 5, 3]Se demostró que estaba equivocado y tengo que usar un diccionario (gracias @Steve). Aquí está la versión actualizada con diccionario incluido:
a = ['pea', 'rpai', 'rpai', 'schiai', 'pea', 'rpe', 'zoi', 'zoi', 'briai', 'rpe'] b = [None]*len(a) d = {} for i,x in enumerate(a): if x not in d: d[x] = len (d) #or use d.setdefault(x, len(d)) instead of the if statement (using the algo from @superb rain's) b[i] = d[x] print (a) print (b)La salida de esto será:
['pea', 'rpai', 'rpai', 'schiai', 'pea', 'rpe', 'zoi', 'zoi', 'briai', 'rpe'] [0, 1, 1, 2, 0, 3, 4, 4, 5, 3]Use un dictado predeterminado y use un contador como una función de valor predeterminado.
Siempre que exista la clave, devuelve la "primera posición encontrada" almacenada; de lo contrario, llama a Incr.__call__ que incrementa su recuento para proporcionar una nueva primera posición encontrada.
Con la sugerencia de super brain, use una clase de contador existente:
from collections import defaultdict from itertools import count li = ['pea', 'rpai', 'rpai', 'schiai', 'pea', 'rpe', 'zoi', 'zoi', 'briai', 'rpe'] seen = defaultdict(count().__next__) print( [seen[val] for val in li] )Haciendo rodar mi propio Incr, como antes, lo que te da la ventaja de que puedes devolver cualquier cosa (como un GUID):
from collections import defaultdict class Incr: def __init__(self): self.count = -1 def __call__(self): self.count +=1 return self.count li = ['pea', 'rpai', 'rpai', 'schiai', 'pea', 'rpe', 'zoi', 'zoi', 'briai', 'rpe'] seen = defaultdict(Incr()) print( [seen[val] for val in li] ) [0, 1, 1, 2, 0, 3, 4, 4, 5, 3]La forma más limpia podría ser usar pandas:
import pandas as pd lst = ['pea', 'rpai', 'rpai', 'schiai', 'pea', 'rpe', 'zoi', 'zoi', 'briai', 'rpe'] pd.factorize(lst)Qué salidas:
(array([0, 1, 1, 2, 0, 3, 4, 4, 5, 3], dtype=int64), array(['pea', 'rpai', 'schiai', 'rpe', 'zoi', 'briai'], dtype=object))