この反復的なリスト成長コードはなぜIndexError:リスト割り当てインデックスが範囲外になるのですか?


194

次のコードを検討してください:

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

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

print j

出力(Win 7 32ビット上のPython 2.6.6)は次のとおりです。

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

それは私には理解できない単純なものだと思います。誰かがそれを片付けることができますか?


6
appendユースケースの適切なソリューションですが、リストのi番目の位置に直接挿入できるpythonリストの挿入メソッドがあります。j.insert(k, l)
opensourcegeek

OPのソリューションが機能しないのはなぜですか?追加を使用する理由
Helen

回答:


317

jは空のリストです[0]が、最初の反復で要素に書き込もうとしていますが、まだ存在していません。

リストの最後に新しい要素を追加するには、代わりに次のことを試してください。

for l in i:
    j.append(l)

もちろん、既存のリストをコピーすることだけが目的の場合は、実際にこれを行うことは決してありません。あなたはただやる:

j = list(i)

または、他の言語の配列のようにPythonリストを使用する場合は、要素をnull値に設定してリストを事前に作成し(None以下の例)、後で特定の位置の値を上書きできます。

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

認識すべきことは、listオブジェクトでは存在しないインデックスに値を割り当てることができないということです。


2
はい、ありがとうございます。ほぼ同じ答えが3つあるので、どれを賞賛すればよいかわかりませんでした。これは私が思う最も記述的なものです。乾杯
ヴラダン

これは、PHPやCのような他の言語から来る人にとって非常に混乱する可能性があることがわかります。jは配列ではなくリストの一種です。リスト型では、これは添え字付きではないと思います。他の言語から来た場合は非常に混乱します。
Nguai al

@Nguaialリストタイプは添え字付きですが、アクセスできるのは既存の要素に限られます。範囲外のインデックスに書き込もうとして要素を作成することはできません。j [0] = "foo"は、リストにすでに少なくとも1つの要素がある場合に機能します。
Steve Mayne

52

他のオプションは初期化することjです:

j = [None] * len(i)

3
maxではなくlen(i)を使用したい。
Steve Mayne

25

j.append(l)代わりにj[k] = lしてk、まったく避けてください。


2
もっと短い(もっとPythonic?)方法かもしれませんj+=[l]
Oleh Prypin

2
@BlaXpirit:ガベージコレクターに負担がかかると思います。
khachik

2
@BalXpirit:それが数文字しか保存しないことを考えると(特に、許容できるようにスペースを追加する必要があるため)、これ.appendははるかに一般的です(おそらく理由があります-理解するのは少し簡単だと思います)。とにかく。(@khachikを編集:いいえ、+=インプレースを変更します)

15

リスト内包表記を使用することもできます。

j = [l for l in i]

または、次のステートメントを使用してコピーを作成します。

j = i[:]

その2番目の構造は
適切

2
唯一の目標がリストのコピーである場合は、j = list(i)と簡単に言うことができます。問題は、要素をコピーする方法を特に必要とするのではなく、リストの動作に関するものだと思います。
Steve Mayne

10
j.append(l)

また、小文字の「L」は1と混同されやすいため、使用しないでください。


7

私はPythonメソッドの挿入があなたが探しているものだと思います:

要素xを位置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
この目的のために特別に提供されたinsert場合appendに使用しても意味がありません。
-holdenweb

情報の点では、コードは実際にはを出力し[1, 20, 2, 3, 4, 5]ます。
holdenweb

インデックス1に挿入し、インデックス1以降を置き換えました。挿入された値はインデックス2で終わりません。Iist.insert()は、リストの最後に項目を追加したくない場合にのみ本当に必要です。ここの質問はそれを正確に行うので、list.append()が推奨されます。
Martijn Pieters

実際になぜ私がそのようにこの質問に答えるのか私も驚かされます:D私が思ったことを知らない:)これは正確に受け入れられた答えである "list.append()"です。私はそれが人々を助けたり、彼らの問題を解決するためのアイデアを与えたりして、5ヒットを得ると思います。

5

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

印刷されます:

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

0から始まる連続したインデックスの場合、特にマッピングが特定の順序を伝えることを目的としていないため、マッピングにスライスまたは逆転がない場合、マッピングは通常、誤ったデータ構造です。
Martijn Pieters

2

もう1つの方法:

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

この場合j、派手な配列になります


弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.