Buat daftar item tunggal yang diulang N kali

523

Saya ingin membuat serangkaian daftar, semua panjang bervariasi. Setiap daftar akan berisi elemen yang sama e, nwaktu yang diulang (di mana n= panjang daftar).

Bagaimana cara membuat daftar, tanpa menggunakan pemahaman daftar [e for number in xrange(n)]untuk setiap daftar?

chimeracoder
sumber

Jawaban:

778

Anda juga dapat menulis:

[e] * n

Anda harus mencatat bahwa jika e misalnya daftar kosong Anda mendapatkan daftar dengan n referensi ke daftar yang sama, bukan n daftar kosong independen.

Pengujian kinerja

Sepintas tampaknya pengulangan adalah cara tercepat untuk membuat daftar dengan n elemen identik:

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

Tapi tunggu - ini bukan ujian yang adil ...

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

Fungsi itertools.repeatsebenarnya tidak membuat daftar, itu hanya membuat objek yang dapat digunakan untuk membuat daftar jika Anda mau! Mari kita coba lagi, tetapi mengonversi ke daftar:

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

Jadi, jika Anda ingin daftar, gunakan [e] * n. Jika Anda ingin membuat elemen dengan malas, gunakan repeat.

Mark Byers
sumber
23
Sangat tidak mungkin bahwa kinerja membuat daftar dengan elemen identik akan menjadi komponen penting dari kinerja program python.
Arthur
11
Seperti disebutkan di atas, jika e adalah daftar kosong [[]] * ndapat menghasilkan hasil yang tidak terduga. Untuk membuat sub-daftar kosong yang unik , gunakan untuk-pemahaman:[[] for i in range(0,n)]
Josiah Yoder
149
>>> [5] * 4
[5, 5, 5, 5]

Hati-hati saat item yang diulang adalah daftar. Daftar tidak akan dikloning: semua elemen akan merujuk ke daftar yang sama!

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

Buat Daftar Item Tunggal Diulang n Kali dengan Python

Barang yang tidak bisa diubah

Untuk item yang tidak dapat diubah, seperti None, bools, ints, float, strings, tuple, atau frozenset, Anda dapat melakukannya seperti ini:

[e] * 4

Perhatikan bahwa ini paling baik digunakan dengan item yang tidak dapat diubah (string, tuple, frozenset,) dalam daftar, karena semuanya menunjuk ke item yang sama di tempat yang sama dalam memori. Saya sering menggunakan ini ketika saya harus membangun sebuah tabel dengan skema dari semua string, sehingga saya tidak harus memberikan pemetaan yang sangat berlebihan.

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

Barang yang bisa diubah

Saya telah menggunakan Python untuk waktu yang lama sekarang, dan saya belum pernah melihat kasus penggunaan di mana saya akan melakukan hal di atas dengan contoh yang bisa berubah. Sebagai gantinya, untuk mendapatkan, katakanlah, daftar kosong yang dapat diubah, set, atau dikte, Anda harus melakukan sesuatu seperti ini:

list_of_lists = [[] for _ in columns]

Garis bawah hanyalah nama variabel sekali pakai dalam konteks ini.

Jika Anda hanya memiliki nomornya, itu akan menjadi:

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

Ini _tidak benar-benar istimewa, tetapi pemeriksa gaya lingkungan pengkodean Anda mungkin akan mengeluh jika Anda tidak bermaksud menggunakan variabel dan menggunakan nama lain.


Peringatan untuk menggunakan metode abadi dengan item yang bisa berubah:

Hati-hati melakukan ini dengan objek yang bisa berubah , ketika Anda mengubah salah satu dari mereka, mereka semua berubah karena mereka semua adalah objek yang sama :

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

foo sekarang kembali:

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

Tetapi dengan objek yang tidak dapat diubah, Anda dapat membuatnya bekerja karena Anda mengubah referensi, bukan objek:

>>> 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([])]

Tetapi sekali lagi, objek yang bisa berubah tidak baik untuk ini, karena operasi di tempat mengubah objek, bukan referensi:

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
sumber
26

Itertools memiliki fungsi hanya untuk itu:

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

Tentu saja itertoolsmemberi Anda iterator, bukan daftar. [e] * nmemberi Anda daftar, tetapi, tergantung pada apa yang akan Anda lakukan dengan urutan itu, itertoolsvarian dapat jauh lebih efisien.

Jochen Ritzel
sumber
13

Seperti yang telah ditunjukkan orang lain, menggunakan operator * untuk objek yang dapat diubah duplikat referensi, jadi jika Anda mengubahnya Anda mengubah semuanya. Jika Anda ingin membuat instance independen dari objek yang bisa diubah, sintaks xrange Anda adalah cara paling Pythonic untuk melakukan ini. Jika Anda merasa terganggu dengan memiliki variabel bernama yang tidak pernah digunakan, Anda dapat menggunakan variabel garis bawah anonim.

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

harus bekerja

Ilmuwan gila
sumber