快速比较数组 [英] Compare arrays in swift
问题描述
试图了解 swift 是如何比较数组的.
Trying to understand how swift compares arrays.
var myArray1 : [String] = ["1","2","3","4","5"]
var myArray2 : [String] = ["1","2","3","4","5"]
// 1) Comparing 2 simple arrays
if(myArray1 == myArray2) {
println("Equality")
} else {
println("Equality no")
}
// -> prints equality -> thanks god
// 2) comparing to a "copy" of an array
// swift copies arrays when passed as parameters (as per doc)
func arrayTest(anArray: [String]) -> Bool {
return anArray == myArray1
}
println("Array test 1 is \(arrayTest(myArray1))")
println("Array test 2 is \(arrayTest(myArray2))")
// equality works for both
myArray2.append("test")
println("Array test 2 is \(arrayTest(myArray2))")
// false (obviously)
myArray2.removeAtIndex(5)
println("Array test 2 is \(arrayTest(myArray2))")
// true
Apple 表示对阵列副本进行了幕后优化.看起来有时 - 并非总是 - 实际上复制或不复制结构.
Apple says there are optimisations behind the scene on array copies. Looks like sometimes - not always - structures are actually copied or not.
说了,
1) is == 遍历所有数组以执行基于元素的比较?(看起来像)-> 那么在非常大的数组上的性能/内存使用情况如何?
1) is == iterating over all the array to perform a element-based comparison ? (looks like it) -> How about performance / memory usage on very large arrays then ?
2) 如果所有元素都相等,我们确定 == 会返回 true 吗?我对 Java 字符串上的 == 有不好的回忆
2) Are we sure == will ever return true if all elements are equal ? I have bad memories of == on Java Strings
3) 有没有办法检查 myArray1 和 myArray2 在技术上是否使用相同的内存位置"/指针等?我在了解优化的工作原理和潜在的警告之后.
3) Is there a way to check if myArray1 and myArray2 are technically using the same "memory location" / pointer / etc. ? i'm after understanding how the optimisation works and potential caveats.
谢谢.
推荐答案
你对 ==
有点紧张是对的:
You’re right to be slightly nervous about ==
:
struct NeverEqual: Equatable { }
func ==(lhs: NeverEqual, rhs: NeverEqual)->Bool { return false }
let x = [NeverEqual()]
var y = x
x == y // this returns true
[NeverEqual()] == [NeverEqual()] // false
x == [NeverEqual()] // false
let z = [NeverEqual()]
x == z // false
x == y // true
y[0] = NeverEqual()
x == y // now false
为什么?Swift 数组不符合 Equatable
,但它们确实有一个 ==
运算符,在标准库中定义为:
Why? Swift arrays do not conform to Equatable
, but they do have an ==
operator, defined in the standard library as:
func ==<T : Equatable>(lhs: [T], rhs: [T]) -> Bool
此运算符循环遍历 lhs
和 rhs
中的元素,比较每个位置的值.它不进行按位比较——它在每对元素上调用==
运算符.这意味着如果您为元素编写自定义 ==
,它将被调用.
This operator loops over the elements in lhs
and rhs
, comparing the values at each position. It does not do a bitwise compare – it calls the ==
operator on each pair of elements. That means if you write a custom ==
for your element, it’ll get called.
但它包含一个优化——如果两个数组的底层缓冲区相同,则不用担心,它只返回 true(它们包含相同的元素,当然它们是相等的!).
But it contains an optimization – if the underlying buffers for the two arrays are the same, it doesn’t bother, it just returns true (they contain identical elements, of course they’re equal!).
这个问题完全是 NeverEqual
等式运算符的错.平等应该是可传递的、对称的和自反的,而这个不是自反的(x == x
是假的).但它仍然可能让你措手不及.
This issue is entirely the fault of the NeverEqual
equality operator. Equality should be transitive, symmetric and reflexive, and this one isn't reflexive (x == x
is false). But it could still catch you unawares.
Swift 数组是写时复制的——所以当你写 var x = y
时,它实际上并没有复制数组,它只是指向 x
y
处的存储缓冲区指针.仅当 x
或 y
稍后发生变异时,它才会复制缓冲区,以便未更改的变量不受影响.这对于数组表现得像值类型但仍然具有高性能至关重要.
Swift arrays are copy-on-write – so when you write var x = y
it doesn’t actually make a copy of the array, it just points x
’s storage buffer pointer at y
’s. Only if x
or y
are mutated later does it then make a copy of the buffer, so that the unchanged variable is unaffected. This is critical for arrays to behave like value types but still be performant.
在 Swift 的早期版本中,您实际上可以在数组上调用 ===
(同样在早期版本中,如果您对 x
进行了变异,变异行为会有所不同), y
也会改变,即使它是用 let
声明的——这吓坏了人们,所以他们改变了它).
In early versions of Swift, you actually could call ===
on arrays (also in early versions, the mutating behaviour was a bit different, if you mutated x
, y
would also change even though it had been declared with let
– which freaked people out so they changed it).
你可以用这个(非常依赖于实现,除了戳和刺激调查之外不依赖于)技巧在数组上重现 ===
的旧行为:
You can kinda reproduce the old behaviour of ===
on arrays with this (very implementation-dependent not to be relied-on except for poking and prodding investigations) trick:
let a = [1,2,3]
var b = a
a.withUnsafeBufferPointer { outer in
b.withUnsafeBufferPointer { inner in
println(inner.baseAddress == outer.baseAddress)
}
}
这篇关于快速比较数组的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!