Mengapa kode tumbuh daftar iteratif ini memberikan IndexError: daftar indeks tugas di luar jangkauan?

194

Silakan pertimbangkan kode berikut:

i = [1, 2, 3, 5, 8, 13]
j = []
k = 0

for l in i:
    j[k] = l
    k += 1

print j

Output (Python 2.6.6 pada Win 7 32-bit) adalah:

> Traceback (most recent call last): 
>     j[k] = l IndexError: list assignment index out of range

Saya kira itu adalah sesuatu yang sederhana yang tidak saya mengerti. Bisakah seseorang membersihkannya?

Vladan
sumber
7
appendadalah solusi yang tepat untuk kasus penggunaan Anda, namun ada metode penyisipan pada daftar python yang dapat menyisipkan langsung ke posisi ke-i dalam daftar. j.insert(k, l)
opensourcegeek
Bolehkah saya bertanya, mengapa solusi OP tidak bekerja? Mengapa menggunakan append?
Helen

Jawaban:

318

jadalah daftar kosong, tetapi Anda mencoba menulis ke elemen [0]di iterasi pertama, yang belum ada.

Coba yang berikut ini sebagai gantinya, untuk menambahkan elemen baru ke akhir daftar:

for l in i:
    j.append(l)

Tentu saja, Anda tidak akan pernah melakukan ini dalam praktik jika yang Anda inginkan adalah menyalin daftar yang ada. Anda baru saja melakukannya:

j = list(i)

Sebagai alternatif, jika Anda ingin menggunakan daftar Python seperti array dalam bahasa lain, maka Anda bisa membuat daftar sebelumnya dengan elemen-elemennya diatur ke nilai nol ( Nonedalam contoh di bawah), dan kemudian, menimpa nilai di posisi tertentu:

i = [1, 2, 3, 5, 8, 13]
j = [None] * len(i)
#j == [None, None, None, None, None, None]
k = 0

for l in i:
   j[k] = l
   k += 1

Yang perlu disadari adalah bahwa suatu listobjek tidak akan memungkinkan Anda untuk menetapkan nilai pada indeks yang tidak ada.

Steve Mayne
sumber
2
OK, terima kasih banyak. Saya tidak tahu yang mana yang harus dipuji karena ada tiga jawaban yang hampir sama. Ini yang paling deskriptif menurut saya. Cheers
Vladan
Saya dapat melihat bahwa ini bisa sangat membingungkan bagi mereka yang datang dari bahasa lain seperti PHP atau C. j adalah jenis daftar, bukan array. Dengan tipe daftar, saya tidak berpikir ini bisa disubkripsikan. Sangat membingungkan jika berasal dari bahasa lain.
Nguai al
@Nguaial Jenis daftar dapat disubkripsikan, tetapi Anda hanya dapat mengakses elemen yang sudah ada - Anda tidak dapat membuat elemen dengan mencoba menulis ke indeks yang berada di luar jangkauan. j [0] = "foo" akan berfungsi jika daftar sudah memiliki setidaknya satu elemen.
Steve Mayne
52

Pilihan Anda yang lain adalah menginisialisasi j:

j = [None] * len(i)
Rsh
sumber
3
Anda ingin menggunakan len (i) daripada maks.
Steve Mayne
25

Lakukan j.append(l)alih-alih j[k] = ldan hindari ksama sekali.

khachik
sumber
2
Cara yang lebih pendek (lebih Pythonic?) Mungkinj+=[l]
Oleh Prypin
2
@BlaXpirit: Saya pikir itu akan membebani pengumpul sampah.
khachik
2
@BalXpirit: Mengingat bahwa hanya menyimpan beberapa karakter (terutama karena Anda perlu menambahkan spasi agar dapat diterima) dan itu .appendjauh lebih umum (mungkin karena suatu alasan - saya pikir ini sedikit lebih mudah untuk dipahami), tidak terlalu unggul dengan cara apapun. (Sunting @khachik: Tidak, +=modifikasi di tempat)
15

Anda juga bisa menggunakan pemahaman daftar:

j = [l for l in i]

atau buat salinannya menggunakan pernyataan:

j = i[:]
Jason Sundram
sumber
konstruksi kedua itu rapi
javadba
2
Jika satu-satunya tujuan adalah menyalin daftar, Anda bisa mengatakan j = daftar (i) Saya pikir pertanyaannya lebih tentang perilaku daftar, daripada secara khusus membutuhkan cara untuk menyalin elemen.
Steve Mayne
10
j.append(l)

Juga hindari menggunakan huruf kecil "L's" karena mudah bagi mereka untuk menjadi bingung dengan 1's

Tom
sumber
7

Saya pikir metode memasukkan Python adalah apa yang Anda cari:

Elemen sisipan x pada posisi i. list.insert (i, x)

array = [1,2,3,4,5]

array.insert(1,20)

print(array)

# prints [1,2,20,3,4,5]
Mehmet Kagan Kayaalp
sumber
1
Tidak ada gunanya menggunakan insertkapan appenddisediakan khusus untuk tujuan ini.
holdenweb
Pada satu titik informasi, kode Anda sebenarnya dicetak [1, 20, 2, 3, 4, 5].
holdenweb
Anda menyisipkan pada indeks 1, menggeser indeks 1 dan seterusnya. Nilai yang dimasukkan tidak berakhir pada indeks 2. Iist.insert () hanya benar-benar diperlukan ketika Anda tidak ingin menambahkan item di akhir daftar; pertanyaan di sini tidak persis seperti itu sehingga list.append () lebih disukai.
Martijn Pieters
Sebenarnya mengapa saya menjawab pertanyaan ini seperti itu saya juga terkejut: D Tidak tahu apa yang saya pikirkan :) Ini persis "list.append ()" yang merupakan jawaban yang diterima. Saya pikir itu membantu orang atau memberikan ide untuk memecahkan masalah mereka sehingga mendapat 5 hit.
Mehmet Kagan Kayaalp
5

Anda bisa menggunakan kamus (mirip dengan array asosiatif) untuk j

i = [1, 2, 3, 5, 8, 13]
j = {} #initiate as dictionary
k = 0

for l in i:
    j[k] = l
    k += 1

print j

akan dicetak:

{0: 1, 1: 2, 2: 3, 3: 5, 4: 8, 5: 13}
Cedric
sumber
Untuk indeks berturut-turut mulai dari 0 pemetaan biasanya struktur data yang salah , terutama ketika pemetaan tidak memiliki pengirisan atau pembalikan karena mereka tidak dimaksudkan untuk menyampaikan urutan tertentu.
Martijn Pieters
2

Satu lagi cara:

j=i[0]
for k in range(1,len(i)):
    j = numpy.vstack([j,i[k]])

Dalam hal ini jakan menjadi array yang numpy

Alex
sumber
0

Mungkin Anda perlu memperpanjang ()

i=[1,3,5,7]
j=[]
j.extend(i)
Fred Moo
sumber