【问题标题】:IndexError: list assignment index out of range , PythonIndexError:列表分配索引超出范围,Python
【发布时间】:2020-02-13 20:46:58
【问题描述】:

我正在尝试实现功能。它的工作方式应该是这样的:

  1. 需要两个列表。
  2. 标记一些索引,最好是中心几个。
  3. 父母双方切换标记的索引。
  4. 其他索引按顺序转到其父元素。
  5. 如果同一个元素已经存在于该父元素中,它会映射并检查其他同一个父元素所在的位置并去那里。
import random
def pm(indA, indB):
    size = min(len(indA), len(indB))
    c1, c2 = [0] * size, [0] * size

    # Initialize the position of each indices in the individuals
    for i in range(1,size):
        c1[indA[i]] = i
        c2[indB[i]] = i

    crosspoint1 = random.randint(0, size)
    crosspoint2 = random.randint(0, size - 1)
    if crosspoint2 >= crosspoint1:
        crosspoint2 += 1
    else:  # Swap the two cx points
        crosspoint1, crosspointt2 = crosspoint2, crosspoint1


    for i in range(crosspoint1, crosspoint2):
        # Keep track of the selected values
        temp1 = indA[i]
        temp2 = indB[i]
        # Swap the matched value
        indA[i], indA[c1[temp2]] = temp2, temp1
        indB[i], indB[c2[temp1]] = temp1, temp2
        # Position bookkeeping
        c1[temp1], c1[temp2] = c1[temp2], c1[temp1]
        c2[temp1], c2[temp2] = c2[temp2], c2[temp1]
        return indA, indB

a,b = pm([3, 4, 8, 2, 7, 1, 6, 5],[4, 2, 5, 1, 6, 8, 3, 7])

错误:

in pm
    c1[indA[i]] = i
IndexError: list assignment index out of range

【问题讨论】:

  • 抱歉,“跨界”?这和基因测序有关吗?
  • @KarlKnechtel 是的,正在尝试实现部分映射的交叉。

标签: python python-3.x list pycharm


【解决方案1】:

不确定您的代码中是否还有其他错误(我没有运行它),但这里是对此的解释。在 Python(与大多数其他语言一样)中,列表(更准确地说是序列)索引基于 0 :

>>> l = [1, 2, 3, 4, 5, 6]
>>>
>>> for e in l:
...     print(e, l.index(e))
...
1 0
2 1
3 2
4 3
5 4
6 5
>>>
>>> l[0]
1
>>> l[5]
6
>>> l[6]
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
IndexError: list index out of range

总结你的问题:

  1. 您的 indA 和 indB 列表各有 6 个元素 ([1..6]),它们的索引:[ 0..5]
  2. 您的 c1 和 c2 列表也有 6 个元素(索引也是 [0..5])
  3. 但是,您使用 #1. 中的值作为 #2. 列表中的索引,并且6 的值是个问题,因为没有这样的索引

要解决您的问题,您应该使用有效的索引值。要么:

  • 在 indA 和 indB 中有正确的值(这是我选择的):

    a, b = pmxCrossover([0, 3, 1, 2, 5, 4], [4, 0, 2, 3, 5, 1])
    
  • 减去 1,无论在哪里遇到来自 indA 或 indB 的值作为索引:

    c1[indA[i] - 1] = i
    

作为一般建议:每当您遇到错误时,添加 print 语句在错误行之前(打印(部分)内容) ,这可能会为您提供线索,帮助您自己解决问题。

@EDIT0

发布(稍微修改的版本)原始代码,带有索引转换:

  • 算法之前:(从每个元素中)减 1 以获得有效索引
  • 算法之后:加 1 以返回基于 1 的索引

code00.py:

#!/usr/bin/env python3

import sys
import random


def pmx_crossover(ind_a, ind_b):
    size = min(len(ind_a), len(ind_b))
    c1, c2 = [0] * size, [0] * size

    # Initialize the position of each indices in the individuals
    for i in range(1, size):
        c1[ind_a[i]] = i
        c2[ind_b[i]] = i
    # Choose crossover points
    crosspoint1 = random.randint(0, size)
    crosspoint2 = random.randint(0, size - 1)
    if crosspoint2 >= crosspoint1:
        crosspoint2 += 1
    else:  # Swap the two cx points
        crosspoint1, crosspointt2 = crosspoint2, crosspoint1

    # Apply crossover between cx points
    for i in range(crosspoint1, crosspoint2):
        # Keep track of the selected values
        temp1 = ind_a[i]
        temp2 = ind_b[i]
        # Swap the matched value
        ind_a[i], ind_a[c1[temp2]] = temp2, temp1
        ind_b[i], ind_b[c2[temp1]] = temp1, temp2
        # Position bookkeeping
        c1[temp1], c1[temp2] = c1[temp2], c1[temp1]
        c2[temp1], c2[temp2] = c2[temp2], c2[temp1]
    return ind_a, ind_b


def main():
    #initial_a, initial_b = [1, 2, 3, 4, 5, 6, 7, 8], [3, 7, 5, 1, 6, 8, 2, 4]
    initial_a, initial_b = [1, 4, 2, 3, 6, 5], [5, 1, 3, 4, 6, 2]
    index_offset = 1
    temp_a = [i - index_offset for i in initial_a]
    temp_b = [i - index_offset for i in initial_b]
    a, b = pmx_crossover(temp_a, temp_b)
    final_a = [i + index_offset for i in a]
    final_b = [i + index_offset for i in b]
    print("Initial: {0:}, {1:}".format(initial_a, initial_b))
    print("Final:   {0:}, {1:}".format(final_a, final_b))


if __name__ == "__main__":
    print("Python {0:s} {1:d}bit on {2:s}\n".format(" ".join(item.strip() for item in sys.version.split("\n")), 64 if sys.maxsize > 0x100000000 else 32, sys.platform))
    main()
    print("\nDone.")

输出(一种可能性(由于random.randint)):

[cfati@CFATI-5510-0:e:\Work\Dev\StackOverflow\q058424002]> "e:\Work\Dev\VEnvs\py_064_03.07.03_test0\Scripts\python.exe" code00.py
Python 3.7.3 (v3.7.3:ef4ec6ed12, Mar 25 2019, 22:22:05) [MSC v.1916 64 bit (AMD64)] 64bit on win32

Initial: [1, 4, 2, 3, 6, 5], [5, 1, 3, 4, 6, 2]
Final:   [1, 3, 2, 4, 6, 5], [5, 1, 4, 3, 6, 2]

Done.

【讨论】:

  • 我的输入列表的值不是 0。当我尝试c1[indA[i] - 1] = i 时,它分配了错误的值。有没有其他方法可以解决这个问题?
  • 是的,它不是,但您可以以 1 实际上是 0 的方式看待事物,依此类推(i 变为 i - 1 )。关于第二个选项,您应该在任何地方都这样做。顺便说一句,您的函数(a 和 b)的预期输出是什么?
  • 它应该创建 2 个新列表。
  • 对不起,我的错。这就是我想要实现的目标:a =[3, 4, 8, 2, 7, 1, 6, 5] b =[4, 2, 5, 1, 6, 8, 3, 7] swapping random index of a and b a =[ , , , 1, 6, 8, , ] b =[ , , , 2, 7, 1, , ] Sequentially filling the values, while skipping repeated value in offspring a = [3, 4, , 1, 6, 8, , 5] b = [4, , 5, 2, 7, 1, 3, ] Updating unfilled values with this mapping: 8 -- 1, 1 is already in the offspring 2 -- 1, 2 occupies this location 6 -- 7, 7 occupies this location New offspring a = [3, 4, 2, 1, 6, 8, 7, 5] b =[4, 8, 5, 2, 7, 1, 3, 6]
  • 工作就像一个魅力。
【解决方案2】:

c1 超出范围,因为在第四个索引处的 for 中,indA[4] 的值是 6。 而c1索引的范围是0-5(长度是6)。

与c1[indA[i]] = i 你试着做c1[6] = 4

【讨论】:

  • 有什么方法可以处理这个或替代方法?
猜你喜欢
  • 2018-10-21
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-03-19
  • 1970-01-01
  • 2022-11-27
  • 2020-09-17
  • 1970-01-01
相关资源
最近更新 更多