Pregunta

Es un problema interesante que busca la solución más pitónica. Supongamos que tengo una lista de asignaciones {'id': id, 'url': url} . Algunos id s en la lista están duplicados, y quiero crear una nueva lista, con todos los duplicados eliminados. Se me ocurrió la siguiente función:

def unique_mapping(map):
    d = {}
    for res in map:
        d[res['id']] = res['url']

    return [{'id': id, 'url': d[id]} for id in d]

Supongo que es bastante eficiente. ¿Pero hay un " más Pythonic " camino ? ¿O tal vez una forma más eficiente?

¿Fue útil?

Solución

Su ejemplo se puede reescribir ligeramente para construir el primer diccionario utilizando una expresión generadora y eliminar la necesidad de construir otras asignaciones. Simplemente reutilice los viejos:

def unique_mapping(mappings):
    return dict((m['id'], m) for m in mappings).values()

Aunque esto salió como una frase, todavía creo que es bastante legible.

Hay dos cosas que debe tener en cuenta al usar su solución original y la mía:

  • los artículos no siempre serán devueltos en el mismo orden en que estaban originalmente
  • la entrada posterior sobrescribirá las entradas anteriores con la misma identificación

Si no le importa, sugiero la solución anterior. En otro caso, esta función conserva el orden y trata los identificadores que se encuentran por primera vez con prioridad:

def unique_mapping(mappings):
    addedIds = set()
    for m in mappings:
        mId = m['id']
        if mId not in addedIds:
            addedIds.add(mId)
            yield m

Puede que necesite llamarlo con list (unique_mappings (mappings)) si necesita una lista y no un generador.

Otros consejos

Hay un par de cosas que podrías mejorar.

  • Estás realizando dos bucles, uno sobre el dict original, y luego nuevamente sobre el dict resultante. En su lugar, puede acumular sus resultados en un solo paso.

  • Puede cambiar para usar un generador, para evitar construir toda la lista por adelantado. (Use list (unique_mapping (items)) para convertir a una lista completa si la necesita)

  • No es necesario almacenar el valor cuando solo busca duplicados, puede usar un conjunto.

  • Estás recreando un diccionario para cada elemento, en lugar de devolver el original. Esto puede ser realmente necesario (por ejemplo, los está modificando y no quiere tocar el original), pero si no, es más eficiente usar los diccionarios ya creados.

Aquí hay una implementación:

def unique_mapping(items):
    s = set()
    for res in items:
        if res['id'] not in s:
            yield res
            s.add(res['id'])

Creo que esto se puede simplificar aún más. Los diccionarios no toleran claves duplicadas. Haga su lista de asignaciones en un diccionario de asignaciones. Esto eliminará los duplicados.

>>> someListOfDicts= [
    {'url': 'http://a', 'id': 'a'}, 
    {'url': 'http://b', 'id': 'b'}, 
    {'url': 'http://c', 'id': 'a'}]

>>> dict( [(x['id'],x) for x in someListOfDicts ] ).values()

[{'url': 'http://c', 'id': 'a'}, {'url': 'http://b', 'id': 'b'}]
Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top