我在Swift中有两个bool
的数组,不一定大小相同,并希望在它们之间进行元素方式的OR。
考虑一下,例如,
var array1 = [false, true, false, true, false, true]
var array2 = [true, true, false, false]
我想要做的是将array2
作为OR掩码应用于array1
的一部分。
如果我要将array2
转录为array1
的一部分,我只会这样做
array1[0..<array2.count] = array2[0..<array2.count]
但我希望能够写出这样的东西:
array1[0..<array2.count] ||= array2[0..<array2.count]
当然无法编译,因为||=
不可用。
一个明确的解决方案是以经典方式迭代元素:
for i in 0..<array2.count {
array1[i] = array1[i] || array2[i]
}
但我想知道是否有更优雅,更像Swift(可能更快?)的解决方案。
答案 0 :(得分:3)
我认为没有理由不能自己定义运营商,例如:
let array1 = [false, true, false, true, false, true]
let array2 = [true, true, false, false]
func ||(lhs: Array<Bool>, rhs: Array<Bool>) -> Array<Bool> {
let shorter: Array<Bool>
let longer: Array<Bool>
if lhs.count < rhs.count {
shorter = lhs
longer = rhs
} else {
longer = lhs
shorter = rhs
}
let shorterProlonged = shorter + longer.suffix(from: shorter.count)
return zip(shorterProlonged, longer).map { $0 || $1 }
}
print(array1 || array2)
答案 1 :(得分:2)
如果通过&#34; Swift-like&#34;你的意思是更具声明性的解决方案,你可以:
zip
数组map
使用压缩元组生成一个&#34; or-ed&#34;阵列以下是它的样子:
let oredArray = zip(array1, array2).map { $0 || $1 }
array1[0 ..< min(oredArray.endIndex, array2.endIndex)] = ArraySlice(oredArray)
但是,这确实需要array1
可变。此外,请注意使用min()
- 它可以防止array2
超过array1
。
答案 2 :(得分:1)
您可以利用全局zip(_:_:)
函数创建截断的压缩序列这一事实,其长度是两个提供的序列中较短的一个。
如果传递给
zip(_:_:)
的两个序列长度不同,那么 结果序列与较短序列的长度相同。
将要转录的数组的索引与要转录的数组的元素进行压缩。例如。构建一个自定义的就地替换中缀运算符:
infix operator ||=: AssignmentPrecedence
func ||=(_ lhs: inout [Bool], rhs: [Bool]) {
zip(0..<lhs.count, rhs).forEach { if !lhs[$0] { lhs[$0] = $1 } }
//or: zip(0..<lhs.count, rhs).forEach { lhs[$0] = lhs[$0] || $1 }
}
使用如下:
// array to be transcribed _into_ longer than the array
// being transcibed from
var array1 = [false, true, false, true, false, true]
var array2 = [true, true, false, false]
array1 ||= array2
print(array1) // [true, true, false, true, false, true]
// array to be transcribed _into_ shorter than the array
// being transcibed from
array2 = [true, true, false, false, true, true, false, false]
array1 ||= array2
print(array1) // [true, true, false, true, true, true]
还请注意@zneak的以下有价值的评论:
&#34;
||
对不同大小的数组的行为对我来说并不明显, 所以我认为使用带有的函数可能很有价值 代表名称而不是运营商。&#34;
所以你可能想考虑将上面的逻辑实现到一个具有语义声音的函数而不是一个运算符。