Tại sao mã phát triển danh sách lặp này cung cấp cho IndexError: chỉ mục gán danh sách ngoài phạm vi?


194

Vui lòng xem xét các mã sau:

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

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

print j

Đầu ra (Python 2.6.6 trên Win 7 32 bit) là:

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

Tôi đoán đó là một cái gì đó đơn giản tôi không hiểu. Ai đó có thể làm sáng tỏ nó?


6
appendlà giải pháp phù hợp cho trường hợp sử dụng của bạn, tuy nhiên có một phương thức chèn vào danh sách python có thể chèn trực tiếp vào vị trí thứ i trong danh sách. j.insert(k, l)
opensourcegeek

Tôi có thể hỏi, tại sao giải pháp của OP không hoạt động? Tại sao sử dụng phụ lục?
Helen

Câu trả lời:


317

jlà một danh sách trống, nhưng bạn đang cố ghi vào phần tử [0]trong lần lặp đầu tiên, chưa tồn tại.

Thay vào đó, hãy thử làm như sau, để thêm một yếu tố mới vào cuối danh sách:

for l in i:
    j.append(l)

Tất nhiên, bạn sẽ không bao giờ làm điều này trong thực tế nếu tất cả những gì bạn muốn làm là sao chép một danh sách hiện có. Bạn chỉ cần làm:

j = list(i)

Ngoài ra, nếu bạn muốn sử dụng danh sách Python như một mảng trong các ngôn ngữ khác, thì bạn có thể tạo trước một danh sách với các thành phần của nó được đặt thành giá trị null ( Nonetrong ví dụ bên dưới) và sau đó, ghi đè lên các giá trị ở các vị trí cụ thể:

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

Điều cần nhận ra là một listđối tượng sẽ không cho phép bạn gán giá trị cho một chỉ mục không tồn tại.


2
OK cảm ơn bạn rất nhiều. Tôi không biết nên khen ai vì có ba câu trả lời gần như giống nhau. Đây là mô tả nhất tôi nghĩ. Chúc mừng
Vladan

Tôi có thể thấy rằng điều này có thể rất khó hiểu đối với những người đến từ các ngôn ngữ khác như PHP hoặc C. j là một loại danh sách, không phải là một mảng. Với loại danh sách, tôi không nghĩ rằng đây là có thể đăng ký. Rất khó hiểu nếu đến từ các ngôn ngữ khác.
Nguai al

@Nguaial Loại danh sách có thể được đăng ký, nhưng bạn chỉ có thể truy cập các phần tử đã tồn tại - bạn không thể tạo một phần tử bằng cách cố gắng ghi vào một chỉ mục nằm ngoài phạm vi. j [0] = "foo" sẽ hoạt động nếu danh sách đã có ít nhất một thành phần.
Steve Mayne

52

Tùy chọn khác của bạn là khởi tạo j:

j = [None] * len(i)

3
Bạn muốn sử dụng len (i) chứ không phải tối đa.
Steve Mayne

25

Làm j.append(l)thay vì j[k] = lvà tránh ktất cả.


2
Một cách ngắn hơn (nhiều Pythonic?) Có thể làj+=[l]
Oleh Prypin

2
@BlaXpirit: Tôi nghĩ sẽ gây gánh nặng cho người thu gom rác.
khachik

2
@BalXpirit: Cho rằng chỉ lưu một vài ký tự (đặc biệt là khi bạn cần thêm khoảng trắng để có thể chấp nhận được) và điều đó .appendphổ biến hơn nhiều (có lẽ vì một lý do - tôi nghĩ nó dễ hiểu hơn một chút), không thực sự vượt trội bằng mọi cách (Chỉnh sửa @khachik: Không, +=sửa đổi tại chỗ)

15

Bạn cũng có thể sử dụng một sự hiểu biết danh sách:

j = [l for l in i]

hoặc tạo một bản sao của nó bằng cách sử dụng câu lệnh:

j = i[:]

công trình thứ hai rất gọn gàng
javadba 17/218

2
Nếu mục tiêu duy nhất là sao chép danh sách, bạn chỉ cần nói j = list (i) Tôi nghĩ rằng câu hỏi liên quan nhiều hơn đến hành vi của danh sách, thay vì cụ thể cần một cách để sao chép các yếu tố.
Steve Mayne

10
j.append(l)

Ngoài ra, tránh sử dụng chữ "L" viết thường vì chúng dễ bị nhầm lẫn với 1


7

Tôi nghĩ rằng chèn phương thức Python là những gì bạn đang tìm kiếm:

Chèn phần tử x vào vị trí i. list.insert (i, x)

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

array.insert(1,20)

print(array)

# prints [1,2,20,3,4,5]

1
Không có điểm sử dụng insertkhi appendđược cung cấp cụ thể cho mục đích này.
Holdenweb

Trên một điểm thông tin, mã của bạn trong thực tế in [1, 20, 2, 3, 4, 5].
Holdenweb

Bạn đã chèn vào chỉ mục 1, thay thế các chỉ số 1 trở đi. Giá trị được chèn không kết thúc tại chỉ mục 2. Iist.insert () chỉ thực sự cần thiết khi bạn không muốn thêm mục vào cuối danh sách; câu hỏi ở đây thực hiện chính xác điều đó vì vậy list.append () là thích hợp hơn.
Martijn Pieters

Trên thực tế tại sao tôi trả lời câu hỏi này như vậy tôi cũng ngạc nhiên: D Không biết tôi nghĩ gì :) Đây chính xác là "list.append ()" là câu trả lời được chấp nhận. Tôi nghĩ rằng nó giúp mọi người hoặc đưa ra một ý tưởng để giải quyết vấn đề của họ để nó được 5 lượt truy cập.
nước

5

Bạn có thể sử dụng một từ điển (tương tự như một mảng kết hợp) cho 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

sẽ in:

{0: 1, 1: 2, 2: 3, 3: 5, 4: 8, 5: 13}

Đối với các chỉ báo liên tiếp bắt đầu từ 0, ánh xạ thường là sai cấu trúc dữ liệu , đặc biệt là khi ánh xạ không có lát hoặc đảo ngược vì chúng không có ý định truyền đạt bất kỳ thứ tự cụ thể nào.
Martijn Pieters

2

Một cách nữa:

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

Trong trường hợp jnày sẽ là một mảng numpy


0

Có lẽ bạn cần gia hạn ()

i=[1,3,5,7]
j=[]
j.extend(i)
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.