Abrufen des Index des Elements während der Verarbeitung einer Liste mithilfe der Karte in Python


74

Während der Verarbeitung einer Liste mit map () möchte ich in Lambda auf den Index des Elements zugreifen. Wie kann ich das machen?

Zum Beispiel

ranked_users = ['jon','bob','jane','alice','chris']
user_details = map(lambda x: {'name':x, 'rank':?}, ranked_users)

Wie kann ich den Rang jedes Benutzers im obigen Beispiel ermitteln?

Antworten:


107

Verwenden Sie Aufzählung :

In [3]: user_details = [{'name':x, 'rank':i} for i,x in enumerate(ranked_users)] 

In [4]: user_details
Out[4]: 
[{'name': 'jon', 'rank': 0},
 {'name': 'bob', 'rank': 1},
 {'name': 'jane', 'rank': 2},
 {'name': 'alice', 'rank': 3},
 {'name': 'chris', 'rank': 4}]

PS. Meine erste Antwort war

user_details = map(lambda (i,x): {'name':x, 'rank':i}, enumerate(ranked_users))

Ich würde dringend empfehlen, immer mapund lambdawann immer möglich ein Listenverständnis oder einen Generatorausdruck zu verwenden. Listenverständnisse sind besser lesbar und lassen sich in der Regel schneller starten.


2
Sollten Lambdas Parameter nicht ohne Klammern stehen?
Dheerosaurier

1
@dheerosaur Nicht in diesem Fall, da die nächste () Operation bei der Aufzählung ein Tupel zurückgibt. Dieses Lambda entspricht def foo ((i, x))
Rod

1
@dheerosaur: Eigentlich sind die Klammern obligatorisch. enumerateerzeugt Tupel (ein einzelnes Objekt).
Unutbu

@ Rod, @ unutbu: Verstanden. Daher können lambdas Tupel nicht wie Listenverständnisse entpacken.
Dheerosaurier

3
@dheerosaur: Ja, Lambdas entpacken anders als Listenverständnisse (in Python2). Beachten Sie, dass Lambdas in Python3 das Auspacken überhaupt ablehnen: Siehe diveintopython3.org/… .
Unutbu

7

Alternativ können Sie ein Listenverständnis anstelle von map () und Lambda verwenden.

ranked_users = ['jon','bob','jane','alice','chris']
user_details = [{'name' : x, 'rank' : ranked_users.index(x)} for x in ranked_users]

Ausgabe:

[{'name': 'jon', 'rank': 0}, {'name': 'bob', 'rank': 1}, {'name': 'jane', 'rank': 2}, {'name': 'alice', 'rank': 3}, {'name': 'chris', 'rank': 4}]

Listenverständnisse sind sehr leistungsfähig und auch schneller als eine Kombination von mapund lambda.


8
list.index()ist nur angemessen, wenn alle Mitglieder von ranked_userseindeutig sind. Gegebene ranked_users = ['chris','chris'] user_detailsAusgaben, [{'name': 'chris', 'rank': 0}, {'name': 'chris', 'rank': 0}]wo es sein sollte [{'name': 'chris', 'rank': 0}, {'name': 'chris', 'rank': 1}].
Thisgeek

Es wäre nur sinnvoll (angesichts dieser Daten), wenn die Mitglieder einzigartig wären…
Prydie

Sicher. Ihre Antwort passt zum Beispiel. Ich dachte nur, es wäre eine gute Idee, die Einschränkung der Einzigartigkeit für jeden darzulegen, der auf diesen Beitrag stößt.
Thisgeek

Die Verwendung des Indexfunktionsaufrufs in der Liste "ranked_users" ist ein wenig überarbeitet. Python für Ausdruck iteriert über Objekte in der Datenstruktur
Cheshire Cat

6

Meiner Meinung nach ging es um die Kartenfunktion, und die bevorzugte Antwort ist teilweise richtig, da Syntaxfehler durch das Setzen von Tupelargumenten auf Lambda verursacht wurden lambda (i,x)

Idee der Aufzählung ist schön und richtige Lösung wäre:

map(lambda x: {'name':x[1], 'rank':x[0]}, enumerate(ranked_users))

und etwas Zeit, um Geschwindigkeit mit Verständnis zu vergleichen:

def with_map():
    ranked_users = range(10 ** 6)
    list(map(lambda x: {'name': x[1], 'rank': x[0]}, enumerate(ranked_users)))

def by_comprehension():
    ranked_users = range(10 ** 6)
    [{'name': x, 'rank': i} for i, x in enumerate(ranked_users)]

from timeit import timeit
time_with_map = timeit(with_map, number=10)
time_with_comprehension = timeit(by_comprehension, number=10)

print('list comprehension is about %.2f x faster than map in this test case' % (time_with_map/time_with_comprehension))

Testergebnis: Das Listenverständnis ist in diesem Testfall etwa 1,31-mal schneller als die Karte


2

Tatsächlich ist hier eine elegantere, ausführlichere Lösung als die Verwendung eines Aufzählungstupels in der Karte (aufgrund der Tupelindizierung). Map kann mehr iterable als Argumente verwenden, also verwenden wir es.

map(lambda user, user_id: (user_id, user), ranked_users, range(ranked_users.__len__()))
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.