Swift 根据另一个布尔数组过滤其他数组

Swift Filter other arrays based on another Bool array

我有一个布尔值数组,我想编辑一个分数数组和一个日期数组,以获得错误的值。我做不到。我想获取错误的元素并使用该数组从分数数组中删除这些元素,但我可以想象有一种直接的方法可以做到这一点。

let hbiCompleteArray = [true, true, true, true, false, true, true, false, false]

let hbiScoreArray = [12, 12, 12, 12, 3, 13, 13, 2, 2]

我想要一组完整的 HbiScores = [12, 12, 12, 12, 13, 13]

如果你必须使用两个数组,你可以用zipfiltermap解决这个问题,如下所示:

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 { [=10=].0 }.map {  }
print(result)

给出:

[12, 12, 12, 12, 13, 13]

解释:zip 交错两个数组(形成一个 (Bool, Int) 元组的数组),然后 filter { [=16=].0 } 只保留 true 布尔值,然后 map 只保留 Int 值。

同意并行数组方法不是用于代码的最佳结构,但 Eric 使用的过滤器和映射的替代方法是 reduce:

let completeHbiScores = zip(hbiCompleteArray, hbiScoreArray).reduce([Int]()){
    (newArray,zippedArray) in
    if zippedArray.0 {
        return newArray + [zippedArray.1]
    }
    else {
        return newArray
    }}

vadian 的评论在这里非常重要。您不应该以这种方式拥有多个数组。创建一个保存数据的结构:

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 { [=12=].isComplete }

当然,如果您只想将最终分数作为数组,则可以映射到:

let finalCompleteScores = completeScores.map { [=13=].finalScore }

这就是您应该如何看待数据,而不是将其视为必须保持同步的一堆数组。

执行此操作的另一种相当简单的方法,它只在您的数组中迭代一次:

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)
}