Индекс списка Python вне диапазона, даже после разделения индексов - PullRequest
0 голосов
/ 25 июня 2018

В приведенном ниже коде я пытаюсь увидеть, является ли следующий элемент данного списка противоположным предыдущему (т. Е. "Север" и "Юг" или "Восток" и "Запад"). Конечно, это вызовет ошибку IndexError, как только мы достигнем последнего элемента списка. Однако я тщательно разграничил цикл for, чтобы он остановился до достижения последнего индекса.

def dirReduc(arr):

for i in range(len(arr)-1):

    if arr[i] == "NORTH" and arr[i+1] == "SOUTH":
        arr.remove("NORTH"), arr.remove("SOUTH")

    elif arr[i] == "SOUTH" and arr[i+1] == "NORTH":
        arr.remove("SOUTH"), arr.remove("NORTH")

    elif arr[i] == "WEST" and arr[i+1] == "EAST":
        arr.remove("WEST"), arr.remove("EAST")

    elif arr[i] == "EAST" and arr[i+1] == "WEST":
        arr.remove("EAST"), arr.remove("WEST")

return arr

Может кто-нибудь объяснить, почему это все еще вызывает IndexError: list out of range?

Вот пример ввода: ["NORTH", "SOUTH", "SOUTH", "EAST", "WEST", "NORTH", "WEST"].

Ответы [ 6 ]

0 голосов
/ 26 июня 2018
def dirReduc(arr):
    if len(arr)-1>0:
       num=  len(arr)-1
       for i in range(num):
           if arr[i] == "NORTH" and arr[i+1] == "SOUTH":
               arr[i]="error", arr[i+1]="error"

           elif arr[i] == "SOUTH" and arr[i+1] == "NORTH":
               arr[i]="error", arr[i+1]="error"
           elif arr[i] == "WEST" and arr[i+1] == "EAST":
               arr[i]="error", arr[i+1]="error"
           elif arr[i] == "EAST" and arr[i+1] == "EAST":
               arr[i]="error", arr[i+1]="error"
    return arr

def main(){
    arr=["EAST","EAST"]#just a example
    arrbuff=[]
    arrbuff.append(dirReduc(arr))#arrbuff is ["error","error"]
    newArr=[];#all correct direction
    for i in range(len(arrbuff)):
        if arrbuff[i] == "error" :
            print("what the error u set hahaha")
        else:
            newArr.append(arrbuff) 
}
0 голосов
/ 25 июня 2018

Ошибка возникает из-за того, что вы перебираете список и удаляете элементы во время каждой итерации.В целом, изменение базового объекта, который вы перебираете, опасно и приведет к интересным ошибкам независимо от языка, на котором вы работаете. Как начинающий программист, вам следует избегать такой практики, если у вас нет веских причин для этого..

Как было предложено, хорошим способом избежать этого является создание копии базового списка и удаление элементов из копии, а не объекта, по которому вы выполняете итерацию.Если вы сделаете это, убедитесь, что вы делаете это правильно .

В качестве другого возможного решения рассмотрите возможность использования словаря для сопоставления каждого направления с противоположным:

opposite = { "NORTH": "SOUTH", "SOUTH": "NORTH", "EAST": "WEST", "WEST": "EAST" } 

Теперь, когда вы перебираете список, вы можете сделать

def consolidate_directions(direction_list):
    directions = []
    # iterating over enumerate(iterable) is like iterating 
    # over iterable except it gives you access to both the current 
    # iteration count and the current item being processed on each iteration
    for i, direction in enumerate(direction_list):
        # this is a trick to avoid out of bounds error when checking for
        # the last element of the list. % is the modulus operator that returns 
        # 0 if the right hand side divides the left hand side evenly. In this 
        # case that would signify the first element of the list, meaning the 
        # current element is the last 
        last_index = (i - 1) % len(direction_list)
        next_index = (i + 1) % len(direction_list)
        if next_index == 0:
            return directions
        else:
            if not (direction_list[next_index] == opposite[direction]) \
             and not (direction_list[last_index] == opposite[direction]):
                directions.append(direction)
    return directions

Более общая обратная связь: большинство программистов на Python используют snake-case для имен функций (как я делал выше) вместо camel-case.Кроме того, одним из преимуществ языка Python является то, что он хорошо читается - он может читать почти как на английском языке.Не стесняйтесь использовать очень описательные имена для ваших переменных и функций.Это облегчает чтение и понимание вашего кода другими программистами, а также облегчает чтение и понимание позже.

Это хорошо описано в Руководстве по стилю PEP-8 , которому вы должны стараться следовать как можно точнее при программировании на Python.

0 голосов
/ 25 июня 2018

Вероятно, ошибка связана со вторым 'elif', поскольку, если arr[i], который вы читаете, соответствует последнему элементу вашего массива, вы не можете рассматривать условие для следующего элемента arr[i + 1], так как вы превышаете длину вашего массива.

0 голосов
/ 25 июня 2018

Это потому, что вы удаляете элемент из списка, затем он продолжает цикл по списку с необновленным len / range.Чтобы избежать этого, можно использовать этот уродливый метод:

def dirReduc(arr):

    for i in range(len(arr)-1):
        if i >= len(arr):
            break
        if arr[i] == "NORTH" and arr[i+1] == "SOUTH":
            arr.remove("NORTH"), arr.remove("SOUTH")

        elif arr[i] == "SOUTH" and arr[i+1] == "NORTH":
            arr.remove("SOUTH"), arr.remove("NORTH")

        elif arr[i] == "WEST" and arr[i+1] == "EAST":
            arr.remove("WEST"), arr.remove("EAST")

        elif arr[i] == "EAST" and arr[i+1] == "WEST":
            arr.remove("EAST"), arr.remove("WEST")

    return arr
0 голосов
/ 25 июня 2018

Не удаляйте элементы из list во время итерации (это приводит к вашей ошибке).Вы можете попробовать эту идею:

def dirReduc(arr):
    expected_list = arr
    for i in range(len(arr) - 1):

        if arr[i] == "NORTH" and arr[i + 1] == "SOUTH":
            expected_list.remove("NORTH"), expected_list.remove("SOUTH")

        elif arr[i] == "SOUTH" and arr[i + 1] == "NORTH":
            expected_list.remove("SOUTH"), expected_list.remove("NORTH")

        elif arr[i] == "WEST" and arr[i + 1] == "EAST":
            expected_list.remove("WEST"), expected_list.remove("EAST")

        elif arr[i] == "EAST" and arr[i + 1] == "WEST":
            expected_list.remove("EAST"), expected_list.remove("WEST")

    return expected_list
0 голосов
/ 25 июня 2018

Проблема в том, что range(len(arr) - 1) возвращает фиксированный объект, который повторяется.Длина массива не пересчитывается на каждой итерации.

Одним из возможных решений является копирование всех элементов, которые вы не хотите "удалять", в другой список.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...