Python trovare l’oggetto in un elenco

Ho un elenco di persone:

[
    {'name' : 'John', 'wins' : 10 },
    {'name' : 'Sally', 'wins' : 0 },
    {'name' : 'Fred', 'wins' : 3 },
    {'name' : 'Mary', 'wins' : 6 }
]

Sto aggiungendo vince utilizzando un elenco di nomi (['Fred', 'Mary', 'Sally']). Non so se il nome è nella lista di persone già, e ho bisogno di inserire un nuovo record, se non. Attualmente sto facendo il seguente:

name = 'John'
person = None
pidx = None
for p in people_list:
    if p['name'] == name:
        person = p
        pidx = people_list.index(p)
        break
if person is None:
    person = {'name' : name, 'wins' : 0}
person['wins'] += 1
if pidx is None:
    people_list.append(person)
else
    people_list[pidx] = person

C’è un modo migliore per fare questo con una lista? Dato che sto salvando questo per MongoDB non posso usare un dict come si salverà come un oggetto e voglio utilizzare array native funzioni per l’ordinamento e la mappatura che non sono disponibili per gli oggetti.

InformationsquelleAutor Josh K | 2011-02-25



5 Replies
  1. 12

    Sto dando per scontato che non si desidera utilizzare qualsiasi struttura diversa da elenco. Il tuo codice dovrebbe funzionare, anche se inutilmente scrivere il dizionario torna alla lista dopo l’aggiornamento. I dizionari sono copiati da riferimento, quindi una volta che si aggiorna, rimane aggiornamento dell’elenco. Dopo un po ‘ di pulizia, il codice potrebbe assomigliare a questo:

    def add_win(people_list, name):
        person = find_person(people_list, name)
        person['wins'] += 1
    
    def find_person(people_list, name):
        for person in people_list:
            if person['name'] == name:
                return person
        person = {'name': name, 'wins': 0}
        people_list.append(person)
        return person
  2. 8

    Sì, uso un dict.

    wins = {}
    for name in winners:
        wins.setdefault(name, 0)
        wins[name] += 1

    edit:

    index = {}
    for name in wins:
        person = index.setdefault(name, { 'name' : name, 'wins': 0 })
        if person['wins'] == 0:
            person_list.append(person)
        person['wins'] += 1
    • Non voglio usare un dict. Voglio usare un list. Dicendo: “utilizza un dict” è inutile perché voglio essere un elenco. Sto salvando questo per MongoDB, utilizzando un dict lo rende un oggetto e voglio utilizzare alcuni nativi funzioni di matrice.
    • K: vedi la mia risposta sull’utilizzo di un list e un set
    • Cosa c’è di non chiaro? So che l’utilizzo di un dict fornirebbe un pulitore di pattern di accesso, ma non posso.
    • la risposta è ancora “utilizzare un dict”. Vedere la mia modifica per come si possono fare entrambe le cose.
  3. 5

    Se non si desidera un dict permanentemente utilizzare uno temporaneamente.

    people = [
        {'name' : 'John', 'wins' : 10 },
        {'name' : 'Sally', 'wins' : 0 },
        {'name' : 'Fred', 'wins' : 3 },
        {'name' : 'Mary', 'wins' : 6 }
    ]
    
    wins = ['Fred', 'Mary', 'Sally']
    
    people_dict = dict((p["name"], p) for p in people)
    
    for winner in wins:
        people_dict[winner].setdefault("wins", 0)
        people_dict[winner]["wins"] += 1
    
    people = people_dict.values()
    • Si può convertire da un list per un dict? Sto tirando un elenco di MongoDB.
    • che è proprio quello che accade nell’esempio di codice nella riga in cui people_dict è definito. La chiave è il nome, il valore è il dict avete.
    • Qual è il carico di elaborazione per la conversione da e per l’elenco / dict?
    • Meno che l’overhead di elaborazione alla ricerca di un elenco ogni volta che si desidera incrementare un numero all’interno di esso.
  4. 3

    Il modello di accesso impone l’uso di una struttura di dati diversi (o almeno un altro helper struttura dei dati). La scansione l’elenco di come si sta facendo è in realtà la cosa giusta da fare, se si utilizza un elenco, ma non si dovrebbe usare una lista (o, se si vuole essere efficiente, in ogni caso).

    Se l’ordine dell’elenco, non importa, si dovrebbe utilizzare un Dizionario (python dict). Se lo fa, si dovrebbe utilizzare un OrderedDict dal collections modulo.

    Si potrebbe anche usare due distinte strutture di dati – l’elenco che hai già, e inoltre un set contenente solo i nomi nell’elenco in modo da avere un rapido accesso a test inclusione o meno. Tuttavia, il set non consentono di accedere con il nome effettivo rapidamente i dati (dovresti ancora fare una ricerca lineare in lista per quello), quindi sarebbe solo essere un utile modello se semplicemente sono stati test di inclusione, ma per il resto sempre a piedi l’elenco è stato inserito.

    Modifica: sembra che quello che si potrebbe effettivamente desidera è un elenco e una dict, dove il dizionario è un mapping tra le name e l’indice nell’elenco. In alternativa si potrebbe ancora utilizzare una dict o OrderedDict, ma li inserisce in Mongo come un array utilizzando dict.iteritems() per creare un array (o quello che potrebbe apparire come un array di Mongo) al momento dell’inserimento. Si potrebbero utilizzare diverse mutator da zip le cose itertools dinamicamente costruire gli oggetti di cui avete bisogno nel vostro risultante matrice.

    • Nota che collections.OrderedDict è di nuovo in Python 2.7, ma non c’è un equivalente ricetta per OrderedDict per le versioni precedenti. Vedi la documentazione per i dettagli.
  5. 0

    Questo specifico caso è implementata dal collections.Counter tipo. Lungo, con vasta gamma di generatori, questa è una espressione:

    [{'name':name, 'wins':wins}
     for name, wins in Counter(names).items()]

    Se si desidera un ordine specifico, sorted() è il modo più semplice (anche questo usa un normale generatore di (), piuttosto che un array generatore [], dal momento che è temporaneo):

    sorted(({'name':name, 'wins':wins} for name, wins in Counter(names).items()),
           key=lambda item: item['name'])

    Dove item['name'] potrebbe essere item['wins'] o di qualsiasi altra espressione paragonabile.

Lascia un commento