Swift фильтрует другие массивы на основе другого массива Bool
У меня есть массив Bools, и я хочу отредактировать массив оценок и массив дат для значений, которые являются ложными. Я не могу до него добраться. Я думал о том, чтобы получить элементы, которые являются ложными, и использовать этот массив, чтобы удалить эти элементы из массива баллов, но я могу представить, что есть прямой способ сделать это.
let hbiCompleteArray = [true, true, true, true, false, true, true, false, false]
let hbiScoreArray = [12, 12, 12, 12, 3, 13, 13, 2, 2]
Мне нужен массив completeHbiScores = [12, 12, 12, 12, 13, 13]
4 ответа:
Если вы должны использовать два массива, вы можете решить это с помощью
zip
,filter
иmap
Вот так:let hbiCompleteArray = [true, true, true, true, false, true, true, false, false] let hbiScoreArray = [12, 12, 12, 12, 3, 13, 13, 2, 2] let result = zip(hbiCompleteArray, hbiScoreArray).filter { $0.0 }.map { $1 } print(result)
Дает:
[12, 12, 12, 12, 13, 13]
Пояснение:
zip
чередует два массива (создает массив кортежей(Bool, Int)
), затемfilter { $0.0 }
сохраняет только булевыtrue
, затемmap
сохраняет только значения Int.
[4] здесь очень важен комментарий вадиана. Вы не должны иметь несколько массивов таким образом. Создайте структуру, содержащую данные:
struct Score { let isComplete: Bool let finalScore: Int }
Затем вы можете добавить дату или любые другие поля, для которых в настоящее время имеются параллельные массивы. Тогда ваши данные выглядят следующим образом:
let scores = [ Score(isComplete: true, finalScore: 12), Score(isComplete: true, finalScore: 12), Score(isComplete: true, finalScore: 12), Score(isComplete: true, finalScore: 12), Score(isComplete: false, finalScore: 3), Score(isComplete: true, finalScore: 13), Score(isComplete: true, finalScore: 13), Score(isComplete: false, finalScore: 2), Score(isComplete: false, finalScore: 2), ]
И получить полные из них просто путем фильтрации
let completeScores = scores.filter { $0.isComplete }
Конечно, если вы хотите получить только итоговые баллы в виде массива, вы можете сопоставить их:
let finalCompleteScores = completeScores.map { $0.finalScore }
Вот как вы должны думать. о ваших данных, а не как куча массивов, которые вы должны синхронизировать.
Согласитесь, что подход параллельных массивов не является лучшей структурой для использования в коде, но альтернативой фильтрам и картам, используемым Eric, является reduce:
let completeHbiScores = zip(hbiCompleteArray, hbiScoreArray).reduce([Int]()){ (newArray,zippedArray) in if zippedArray.0 { return newArray + [zippedArray.1] } else { return newArray }}
Еще один довольно простой способ сделать это, который повторяется только один раз через ваши массивы:
let hbiCompleteArray = [true, true, true, true, false, true, true, false, false] let hbiScoreArray = [12, 12, 12, 12, 3, 13, 13, 2, 2] var completeHbiScores = [Int]() for score in hbiScoreArray.enumerated() { // break out of the loop if we're at the end of hbiCompleteArray // assuming that no value means default to false guard score.offset < hbiCompleteArray.count else { break } // go to the next score if the current element is false guard hbiCompleteArray[score.offset] else { continue } completeHbiScores.append(score.element) }