快速比较数组 [英] Compare arrays in swift

查看:27
本文介绍了快速比较数组的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

试图了解 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

此运算符循环遍历 lhsrhs 中的元素,比较每个位置的值.它进行按位比较——它在每对元素上调用==运算符.这意味着如果您为元素编写自定义 ==,它将被调用.

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 时,它实际上并没有复制数组,它只是指向 xy 处的存储缓冲区指针.仅当 xy 稍后发生变异时,它才会复制缓冲区,以便未更改的变量不受影响.这对于数组表现得像值类型但仍然具有高性能至关重要.

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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆