Swift zip生成器仅迭代一侧两次
我在两个元组数组上使用Swift zip生成器仅迭代一侧两次,swift,collections,standard-library,Swift,Collections,Standard Library,我在两个元组数组上使用zip。迭代结果时,结果元组仅包含左侧的元组 有趣的是,Array(zip(…)按预期生成一个集合。我希望节省一些周期和内存,并且不希望仅仅为了循环而生成新数组 let expectation: [(String, UInt)] = [("bar", 0)] let comparison: [(String, Int)] = [("foo", 0)] func ==(lhs: [(String, UInt)], rhs: [(String, Int)]) -> Bo
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对我来说毫无用处(除非你能解释发生了什么)。无法确定这是一个bug还是我不理解的东西(怀疑bug,但需要更多地使用它) 但是,同时还有一个解决方法,它涉及到对数据的完全分解:
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
func-equal(lhs:[T],rhs:[U],IseEquivalent:(T,U)->Bool)->Bool{
如果lhs.count!=rhs.count{return false}
return!contains(zip(lhs,rhs)){!IseEquivalent($0)}
}
//现在,上面使用的equal将编译并返回正确的结果
p、 您可能希望为
UInt
转换添加溢出检查以支持@Airspeed Velocity,这似乎是一个错误,因为您只能定义第一个元组,而第二个元组将按预期工作:-/
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
是的,看起来像只虫子。但奇怪的是,如果将for循环替换为contains(),则不需要解构元组,它的工作方式与预期的一样:
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
}
}
是的,这让我确信这是一只虫子。在6.4中被破坏的牙齿看起来非常光滑!如果您想变得非常简洁,可以将其全部放在一条语句中:
return lhs.endIndex==rhs.endIndex&!包含(zip(lhs,rhs)){$0.0!=$1.0 | | Int($0.1)!=$1.1}
,但它的速度大约是其他选项的一半。哦,好吧,所以我提交了我的第一个错误报告,很棒:)rdar://21096510