Перебирая коллекцию и удаляя вещи по пути - PullRequest
1 голос
/ 14 мая 2019

Я хочу просмотреть коллекцию и найти первую пару подходящих элементов, но мой текущий подход испытывает проблемы с постоянным выходом индексации за пределы.

Вот упрощенный пример MWE:

function processstuff(stuff)
    for pointer1 in 1:length(stuff)
        for pointer2 in pointer1:length(stuff)
            println("$(stuff)")
            pointer1 == pointer2 && continue
            if stuff[pointer1] == stuff[pointer2]
                # items match, remove them
                deleteat!(stuff, pointer1)
                deleteat!(stuff, pointer2)
            end
        end
    end
end

processstuff(collect(rand(1:5, 20)))

[1, 4, 3, 3, 2, 4, 5, 2, 2, 2, 3, 1, 2, 1, 2, 4, 3, 2, 1, 1]
[1, 4, 3, 3, 2, 4, 5, 2, 2, 2, 3, 1, 2, 1, 2, 4, 3, 2, 1, 1]
[1, 4, 3, 3, 2, 4, 5, 2, 2, 2, 3, 1, 2, 1, 2, 4, 3, 2, 1, 1]
[1, 4, 3, 3, 2, 4, 5, 2, 2, 2, 3, 1, 2, 1, 2, 4, 3, 2, 1, 1]
[1, 4, 3, 3, 2, 4, 5, 2, 2, 2, 3, 1, 2, 1, 2, 4, 3, 2, 1, 1]
[1, 4, 3, 3, 2, 4, 5, 2, 2, 2, 3, 1, 2, 1, 2, 4, 3, 2, 1, 1]
[1, 4, 3, 3, 2, 4, 5, 2, 2, 2, 3, 1, 2, 1, 2, 4, 3, 2, 1, 1]
[1, 4, 3, 3, 2, 4, 5, 2, 2, 2, 3, 1, 2, 1, 2, 4, 3, 2, 1, 1]
[1, 4, 3, 3, 2, 4, 5, 2, 2, 2, 3, 1, 2, 1, 2, 4, 3, 2, 1, 1]
[1, 4, 3, 3, 2, 4, 5, 2, 2, 2, 3, 1, 2, 1, 2, 4, 3, 2, 1, 1]
[1, 4, 3, 3, 2, 4, 5, 2, 2, 2, 3, 1, 2, 1, 2, 4, 3, 2, 1, 1]
[1, 4, 3, 3, 2, 4, 5, 2, 2, 2, 3, 1, 2, 1, 2, 4, 3, 2, 1, 1]
[4, 3, 3, 2, 4, 5, 2, 2, 2, 3, 1, 1, 2, 4, 3, 2, 1, 1]
[4, 3, 3, 2, 4, 5, 2, 2, 2, 3, 1, 1, 2, 4, 3, 2, 1, 1]
[3, 3, 2, 4, 5, 2, 2, 2, 3, 1, 1, 2, 4, 2, 1, 1]
[3, 3, 2, 4, 5, 2, 2, 2, 3, 1, 1, 2, 4, 2, 1, 1]
[3, 3, 2, 4, 5, 2, 2, 2, 3, 1, 1, 2, 4, 2, 1, 1]
ERROR: LoadError: BoundsError: attempt to access 16-element Array{Int64,1} at index [17]

(Очевидно, этот пример сравнивает только два числа, а реальное сравнение - нет.)

Идея обновления коллекции элементов путем удаления обоих обработанных элементов выглядит следующим образомэто работает, потому что я думаю, что Джулия обновляет итерацию каждый раз до конца.Но только ненадолго ...?

1 Ответ

1 голос
/ 14 мая 2019

Вы можете использовать следующий подход (при условии, что вы хотите удалить пары):

function processstuff!(stuff)
    pointer1 = 1
    while pointer1 < length(stuff)
        for pointer2 in pointer1+1:length(stuff)
            if stuff[pointer1] == stuff[pointer2]
                deleteat!(stuff, (pointer1, pointer2))
                pointer1 -= 1 # correct pointer location as we later add 1 to it
                break
            end
        end
        pointer1 += 1
    end
end

В вашем коде было несколько проблем:

  • вы дважды звонили deleteat!, что может сделать недействительной индексацию
  • , которую ваш внутренний цикл пытался удалить pointer1 несколько раз
  • во внешнем цикле. Я использую while для динамического отслеживания изменения размера stuff
...