Question

C’est un problème intéressant qui cherche la solution la plus pythonique. Supposons que j'ai une liste de mappages {'id': id, 'url': url} . Certains éléments id de la liste sont en double et je souhaite créer une nouvelle liste en supprimant tous les doublons. Je suis venu avec la fonction suivante:

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

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

Je suppose que c'est assez efficace. Mais existe-t-il un "plus pythonique"? façon ? Ou peut-être un moyen plus efficace?

Était-ce utile?

La solution

Votre exemple peut être légèrement réécrit pour construire le premier dictionnaire à l'aide d'une expression génératrice et supprimer la nécessité de construire d'autres mappages. Il suffit de réutiliser les anciens:

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

Même si cela est sorti comme une ligne, je pense toujours que c'est assez lisible.

Il y a deux choses que vous devez garder à l'esprit lorsque vous utilisez votre solution d'origine et la mienne:

  • les articles ne seront pas toujours renvoyés dans le même ordre qu'ils étaient à l'origine
  • la dernière entrée écrasera les entrées précédentes avec le même identifiant

Si cela ne vous dérange pas, je suggère la solution ci-dessus. Dans les autres cas, cette fonction préserve l’ordre et traite les identifiants rencontrés en premier avec la priorité:

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

Vous devrez peut-être l'appeler avec la liste (unique_mappings (mappings)) si vous avez besoin d'une liste et non d'un générateur.

Autres conseils

Il y a plusieurs choses que vous pourriez améliorer.

  • Vous effectuez deux boucles, une sur le dict d'origine, puis à nouveau sur le résultat. Vous pouvez créer vos résultats en une étape à la place.

  • Vous pouvez changer pour utiliser un générateur, pour éviter de construire la liste complète au début. (Utilisez list (unique_mapping (items)) pour convertir en une liste complète si vous en avez besoin)

  • Il n'est pas nécessaire de stocker la valeur lors de la vérification des doublons, vous pouvez utiliser un ensemble.

  • Vous recréez un dictionnaire pour chaque élément plutôt que de renvoyer l'original. Cela peut en fait être nécessaire (par exemple, vous les modifiez et vous ne voulez pas toucher à l'original), mais sinon, il est plus efficace d'utiliser les dictionnaires déjà créés.

Voici une implémentation:

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

Je pense que cela peut encore être simplifié. Les dictionnaires ne tolèrent pas les clés en double. Faites votre liste de mappages dans un dictionnaire de mappages. Cela supprimera les doublons.

>>> 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'}]
Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top