Erstellen Sie eine Liste einzelner Elemente, die N-mal wiederholt wird

523

Ich möchte eine Reihe von Listen unterschiedlicher Länge erstellen. Jede Liste enthält das gleiche Element e, das wiederholt wiederholt nwird (wobei n= Länge der Liste).

Wie erstelle ich die Listen, ohne [e for number in xrange(n)]für jede Liste ein Listenverständnis zu verwenden?

Chimäre
quelle

Antworten:

778

Sie können auch schreiben:

[e] * n

Sie sollten beachten, dass wenn e beispielsweise eine leere Liste ist, Sie eine Liste mit n Verweisen auf dieselbe Liste erhalten, nicht n unabhängigen leeren Listen.

Leistungstest

Auf den ersten Blick scheint Wiederholung der schnellste Weg zu sein, um eine Liste mit n identischen Elementen zu erstellen:

>>> timeit.timeit('itertools.repeat(0, 10)', 'import itertools', number = 1000000)
0.37095273281943264
>>> timeit.timeit('[0] * 10', 'import itertools', number = 1000000)
0.5577236771712819

Aber warte - es ist kein fairer Test ...

>>> itertools.repeat(0, 10)
repeat(0, 10)  # Not a list!!!

Die Funktion itertools.repeaterstellt die Liste nicht wirklich, sondern nur ein Objekt, mit dem Sie auf Wunsch eine Liste erstellen können! Versuchen wir das noch einmal, aber konvertieren Sie in eine Liste:

>>> timeit.timeit('list(itertools.repeat(0, 10))', 'import itertools', number = 1000000)
1.7508119747063233

Wenn Sie also eine Liste möchten, verwenden Sie [e] * n. Wenn Sie die Elemente träge generieren möchten, verwenden Sie repeat.

Mark Byers
quelle
23
Es ist sehr unwahrscheinlich, dass die Leistung beim Erstellen einer Liste mit identischen Elementen ein kritischer Bestandteil der Leistung eines Python-Programms ist.
Arthur
11
Wie oben erwähnt, kann eine leere Liste zu [[]] * nunerwarteten Ergebnissen führen. Um eindeutige leere Unterlisten zu erstellen , verwenden Sie zum Verständnis:[[] for i in range(0,n)]
Josiah Yoder
149
>>> [5] * 4
[5, 5, 5, 5]

Seien Sie vorsichtig, wenn es sich bei dem wiederholten Element um eine Liste handelt. Die Liste wird nicht geklont: Alle Elemente verweisen auf dieselbe Liste!

>>> x=[5]
>>> y=[x] * 4
>>> y
[[5], [5], [5], [5]]
>>> y[0][0] = 6
>>> y
[[6], [6], [6], [6]]
gaefan
quelle
80

Erstellen Sie eine Liste einzelner Elemente, die n Mal in Python wiederholt wurden

Unveränderliche Gegenstände

Für unveränderliche Gegenstände wie Keine, Bools, Ints, Floats, Strings, Tupel oder Frozensets können Sie dies folgendermaßen tun:

[e] * 4

Beachten Sie, dass dies am besten nur für unveränderliche Elemente (Zeichenfolgen, Tupel, Frozensets) in der Liste verwendet wird, da alle auf dasselbe Element an derselben Stelle im Speicher verweisen. Ich verwende dies häufig, wenn ich eine Tabelle mit einem Schema aller Zeichenfolgen erstellen muss, damit ich keine hochredundante Eins-zu-Eins-Zuordnung vornehmen muss.

schema = ['string'] * len(columns)

Veränderliche Gegenstände

Ich habe Python schon lange verwendet und noch nie einen Anwendungsfall gesehen, in dem ich das oben Genannte mit einer veränderlichen Instanz tun würde. Um beispielsweise eine veränderbare leere Liste, einen Satz oder ein Diktat zu erhalten, sollten Sie Folgendes tun:

list_of_lists = [[] for _ in columns]

Der Unterstrich ist in diesem Zusammenhang einfach ein wegwerfbarer Variablenname.

Wenn Sie nur die Nummer haben, wäre das:

list_of_lists = [[] for _ in range(4)]

Das _ist nicht wirklich speziell, aber Ihr Stilprüfer für die Codierungsumgebung wird sich wahrscheinlich beschweren, wenn Sie nicht beabsichtigen, die Variable zu verwenden und einen anderen Namen zu verwenden.


Vorsichtsmaßnahmen für die Verwendung der unveränderlichen Methode bei veränderlichen Elementen:

Beachten Sie dies bei veränderlichen Objekten . Wenn Sie eines davon ändern, ändern sich alle, weil sie alle dasselbe Objekt sind:

foo = [[]] * 4
foo[0].append('x')

foo kehrt jetzt zurück:

[['x'], ['x'], ['x'], ['x']]

Bei unveränderlichen Objekten kann dies jedoch funktionieren, da Sie die Referenz und nicht das Objekt ändern:

>>> l = [0] * 4
>>> l[0] += 1
>>> l
[1, 0, 0, 0]

>>> l = [frozenset()] * 4
>>> l[0] |= set('abc')
>>> l
[frozenset(['a', 'c', 'b']), frozenset([]), frozenset([]), frozenset([])]

Aber auch hier sind veränderbare Objekte nicht gut dafür, da In-Place-Operationen das Objekt und nicht die Referenz ändern:

l = [set()] * 4
>>> l[0] |= set('abc')    
>>> l
[set(['a', 'c', 'b']), set(['a', 'c', 'b']), set(['a', 'c', 'b']), set(['a', 'c', 'b'])]
Aaron Hall
quelle
26

Itertools hat eine Funktion nur dafür:

import itertools
it = itertools.repeat(e,n)

Natürlich itertoolsgibt es einen Iterator anstelle einer Liste. [e] * ngibt Ihnen eine Liste, aber je nachdem, was Sie mit diesen Sequenzen machen, kann die itertoolsVariante viel effizienter sein.

Jochen Ritzel
quelle
13

Wie andere bereits betont haben, dupliziert die Verwendung des Operators * für ein veränderbares Objekt Verweise. Wenn Sie also einen ändern, ändern Sie alle. Wenn Sie unabhängige Instanzen eines veränderlichen Objekts erstellen möchten, ist Ihre xrange-Syntax die pythonischste Methode, um dies zu tun. Wenn Sie Probleme mit einer benannten Variablen haben, die niemals verwendet wird, können Sie die anonyme Unterstrichvariable verwenden.

[e for _ in xrange(n)]
WP McNeill
quelle
10
[e] * n

sollte arbeiten

Verrückter Wissenschaftler
quelle