我在两个元组数组上使用 zip
。当我迭代结果时,结果元组仅包含左侧的元组。
有趣的是,Array(zip(...))
按预期生成了一个集合。我想节省一些周期和内存,并且不想为了循环而生成一个新数组。
let expectation: [(String, UInt)] = [("bar", 0)]
let comparison: [(String, Int)] = [("foo", 0)]
func ==(lhs: [(String, UInt)], rhs: [(String, Int)]) -> Bool {
if lhs.count != rhs.count {
return false
}
for (l, r) in zip(lhs, rhs) {
// Looking at `l` and `r` in lldb shows both are the same.
if l.0 != r.0 || Int(l.1) != r.1 {
return false
}
}
return true
}
let equals = (expectation == comparison) // true?!?!
这是一种方便的方法,可以将测试替身中的函数调用记录与来自实际测试用例的测试数据进行比较。双记录 (String, UInt)
,在测试用例中键入元组会产生 (String, Int)
,所以我想:让我们创建一个简单的相等函数吧!将 UInt
更改为 Int
不会改变任何事情。
怎么样?渲染 zip 对我来说毫无用处(除非你能解释发生了什么)。
最佳答案
无法确定这是一个错误还是我不理解的东西(怀疑是错误但需要更多地尝试)。
但是,同时这里有一个解决方法,它涉及完全解构数据:
let expectation: [(String, UInt)] = [("bar", 0)]
let comparison: [(String, Int)] = [("foo", 1)]
func ==(lhs: [(String, UInt)], rhs: [(String, Int)]) -> Bool {
if lhs.count != rhs.count {
return false
}
for ((ls, li),(rs,ri)) in zip(lhs, rhs) {
// Looking at `l` and `r` in lldb shows both are the same.
if ls != rs || Int(li) != ri {
return false
}
}
return true
}
let equals = (expectation == comparison) // now returns false
理论上,这应该更容易写成:
equal(expectation, comparison) {
$0.0 == $1.0 && Int($0.1) == $1.1
}
除了令人恼火的是,采用谓词的equal
函数仍然要求两个序列的元素相同!雷达 17590938。
针对此特定于数组的快速修复可能如下所示:
func equal<T,U>(lhs: [T], rhs: [U], isEquivalent: (T,U)->Bool) -> Bool {
if lhs.count != rhs.count { return false }
return !contains(zip(lhs, rhs)) { !isEquivalent($0) }
}
// now the above use of equal will compile and return the correct result
附注您可能想为 UInt
转换添加溢出检查
关于Swift zip 生成器只迭代一侧两次,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/30413020/