Arrays Swift根据另一个布尔数组筛选其他数组

Arrays Swift根据另一个布尔数组筛选其他数组,arrays,swift,filter,flatmap,Arrays,Swift,Filter,Flatmap,我有一个布尔值数组,我想编辑一个分数数组和一个日期数组,用于假值。我去不了。我曾想过获取错误的元素,并使用该数组从分数数组中删除这些元素,但我可以想象有一种直接的方法可以做到这一点 let hbiCompleteArray = [true, true, true, true, false, true, true, false, false] let hbiScoreArray = [12, 12, 12, 12, 3, 13, 13, 2, 2] 我想要一个completeHbiScores

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

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]

如果必须使用两个数组,可以使用
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
布尔值,然后,
映射
只保留Int值。

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

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

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

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 }

这是您应该如何考虑数据,而不是作为一组必须保持同步的数组。另一种相当简单的方法是只在数组中迭代一次:

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)
}
让hbiCompleteArray=[真、真、真、假、真、真、假、假]
设hbiScoreArray=[12,12,12,3,13,13,2,2]
变量completeHbiScores=[Int]()
对于hbiScoreArray.enumerated()中的分数{
//如果我们在hbiCompleteArray的末尾,就打破循环
//假设没有值意味着默认为false
后卫得分.offset
考虑为模型使用自定义结构的一个数组,而不是多个数组。哦,听起来太酷了,我该怎么做呢?如果数组不是太大,这是一种很好且相当简单的方法。唯一的问题是,这些操作中的每一个都会在数组中迭代,因此它可能会在大型数组上陷入困境。足够优化吗?这取决于您的决定,当然不要选择更复杂的解决方案,除非测试表明它对于您的需求来说太慢。@ColGraff它确实会重复多次,但我认为这不是问题,甚至不是问题。我们可以猜测OP在他们的数组中不会有几十亿的分数——此外,Zip2Sequence(不是实际的数组)的性质以及过滤器/映射经过优化(缓冲区、写时复制、编译器优化等)的事实让我说这里真的没问题。:)我同意这可能不是一个问题,在不测试瓶颈的情况下切换到另一个解决方案肯定是过早的优化。使用这个简单明了的解决方案,如果测试显示它是一个瓶颈,那么就对它进行优化。这应该是大多数软件开发的指南!请注意,您也可以使用
flatMap
而不是
filter
map
,例如
let result=zip(hbiCompleteArray,hbiscoreraray)。flatMap{$0?$1:nil}
:)运行良好,非常优雅。现在尝试使用相同的方法返回日期数组。谢谢这当然是最好的解决方案如果你能把你的数据放在一个结构中,它通常会使代码更干净,更容易维护。如果出于其他设计原因,您必须有两个数组,那么其他解决方案可能会更好。我喜欢这个解决方案,因为我还可以添加分数日期。然后,我可以使用图表的日期/分数。我以后再试试。