Удалить элементы из строкового массива, находясь в a для l oop, чье условие зацикливания зависит от размера строкового массива - PullRequest
0 голосов
/ 03 апреля 2020

У меня есть строковый массив, из которого я хочу удалить элементы в зависимости от значений в массиве indexPath, сгенерированного жестом панорамирования двумя пальцами по строкам таблицы. Число повторений l oop зависит от размера массива строк, и соответствующий элемент массива строк удаляется для каждого l oop.

Код ниже:

if let indexPaths = languagesTable.indexPathsForSelectedRows {
    rowCount = rowCount - (indexPaths.count)     
    controllerData.deleteWordsForLanguage(languages: languages, indexPaths: indexPaths)        
    for indexPath in indexPaths {
        print("inside 1st for loop in clearSelectedLanguages, indexPaths are: \(indexPaths)")
        print("languages.count in clearSelectedLanguages in languagesView os: \(languages.count)")
        for language in 0..<languages.count 
            print("indexPath.row == language is: \(indexPath.row == language) && indexPath.section == 0 is: \(indexPath.section == 0)")
            if indexPath.row == language && indexPath.section == 0 {
                print("inside 2nd for loop in clearSelectedLanguages in languages")
                print("languages in clearSelectedLanguages before languages.remove in languagesView are: \(languages)")
                languages.remove(at: language)
                print("languages in clearSelectedLanguages in languagesView are: \(languages)")
                }
            }
        }
    }
    controllerData.saveLanguages(languagesToSave: languages)
    languagesTable.setEditing(false, animated: true)
    languagesTable.reloadData()
    enableSort()
    enableDelete()
}

Когда я прошу приложение удалить (нажав кнопку удаления) все элементы массива строк, оно удаляет все элементы, кроме одного. Я пытался расположить элементы строкового массива в разных порядках, и это не похоже на значение строкового элемента, указывающее c, просто всегда средний элемент, если это был массив из 3 элементов.

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

Некоторые выходные данные отладочной консоли:

inside 1st for loop in clearSelectedLanguages, indexPaths are: [[0, 0], [0, 1], [0, 2]]
indexPath.row == language is: true && indexPath.section == 0 is: true
inside 2nd for loop in clearSelectedLanguages in languages
languages in clearSelectedLanguages in languagesView are: ["french", "spanish", "german"]
languages in clearSelectedLanguages in languagesView are: ["spanish", "german"]
indexPath.row == language is: false && indexPath.section == 0 is: true
indexPath.row == language is: false && indexPath.section == 0 is: true
inside 1st for loop in clearSelectedLanguages, indexPaths are: [[0, 0], [0, 1], [0, 2]]
indexPath.row == language is: false && indexPath.section == 0 is: true
indexPath.row == language is: true && indexPath.section == 0 is: true
inside 2nd for loop in clearSelectedLanguages in languages
languages in clearSelectedLanguages in languagesView are: ["spanish", "german"]
languages in clearSelectedLanguages in languagesView are: ["spanish"]
inside 1st for loop in clearSelectedLanguages, indexPaths are: [[0, 0], [0, 1], [0, 2]]
indexPath.row == language is: false && indexPath.section == 0 is: true
languages in saveLanguages in dataModel are: ["spanish"]

Как видите, второй набор условий if не выполняется, и последний элемент массива строк никогда не удаляется. Затем программа завершает все циклы и вызывает метод, который включает в себя окончательный отладочный оператор печати. ​​

1 Ответ

1 голос
/ 03 апреля 2020

Использование al oop для удаления элементов по индексам часто сбивает нас с толку, поскольку целевой индекс будет изменяться при выполнении l oop.

, когда indexPaths задано как [[0, 0], [0, 1], [0, 2]], а languages как ["french", "spanish", "german"],

  • [0, 0] для "french"
  • [0, 1] для "spanish"
  • [0, 2] для "german"

При удалении первого indexPath [0, 0] все может быть в порядке:

languages in clearSelectedLanguages in languagesView are: ["french", "spanish", "german"]
languages in clearSelectedLanguages in languagesView are: ["spanish", "german"]

удаляет соответствующий элемент "french".

Но при удалении второго indexPath [0, 1], вам может потребоваться тщательно проверить вывод.

languages in clearSelectedLanguages in languagesView are: ["spanish", "german"]
languages in clearSelectedLanguages in languagesView are: ["spanish"]

Удаляет (первоначально) третий элемент "german", а не второй элемент "spanish". Поскольку после удаления элемента индексы каждого элемента в массиве изменятся.

Итак, когда вы хотите удалить третий indexPath [0, 2], ничего не происходит, так как отдельный элемент Array ["spanish"] не имеет элемент индекса 2.


Один из способов справиться с этой ситуацией - удалить в обратном порядке, снизу вверх.

    for indexPath in indexPaths.reversed() {
        //...
    }

Но двойной l oop не эффективный способ, и я написал бы это следующим образом:

        if let indexPaths = languagesTable.indexPathsForSelectedRows {
            rowCount = rowCount - (indexPaths.count)
            controllerData.deleteWordsForLanguage(languages: languages, indexPaths: indexPaths)

            print("indexPaths are: \(indexPaths)")
            let rowsToRemove = Set(indexPaths.filter{$0.section == 0}.map{$0.row})
            print("languages before filter are: \(languages)")
            languages = languages.enumerated().filter{row,_ in !rowsToRemove.contains(row)}.map{$1}
            print("languages after filter are: \(languages)")

            controllerData.saveLanguages(languagesToSave: languages)
            //...
        }

Пожалуйста, попробуйте.

...