我在两个元组数组上使用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?!?!
这是一种方便的方法,用于比较测试double中的函数调用记录以及测试来自实际测试用例的数据。双记录(String, UInt)
,在测试用例中输入元组会产生(String, Int)
,所以我想:让我们创建一个简单的相等函数!将UInt
更改为Int
并不会改变任何事情。
怎么样?渲染拉链对我来说毫无用处(除非你能解释发生了什么)。
答案 0 :(得分:3)
无法确定这是一个错误还是我不理解的东西(可疑的错误,但需要更多地使用它)。
但是,这是平均时间的一种解决方法,它涉及对数据进行完全解构:
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
P.S。您可能希望为UInt
转化
答案 1 :(得分:2)
为了支持@Airspeed Velocity,它似乎是一个bug,因为你只能定义第一个元组,而第二个元组将按预期工作: - / Xcode 6.3.2 Swift 1.2
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 ((l0, l1), r) in zip(lhs, rhs) {
// Explicitly detiled first tuple
if l0 != r.0 || Int(l1) != r.1 {
return false
}
}
return true
}
let equals = (expectation == comparison) // false as expected
答案 2 :(得分:1)
是的,看起来像个臭虫。奇怪的是,如果你用contains()替换for循环,你不需要解构元组,它就像你期望的那样工作:
func ==(lhs: [(String, UInt)], rhs: [(String, Int)]) -> Bool {
if lhs.count != rhs.count {
return false
}
return !contains(zip(lhs, rhs)) {
l, r in l.0 != r.0 || Int(l.1) != r.1
}
}