Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Compare arrays in 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 says there are optimisations behind the scene on array copies. Looks like sometimes - not always - structures are actually copied or not.

That said,

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) Are we sure == will ever return true if all elements are equal ? I have bad memories of == on Java Strings

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.

Thanks.

like image 319
vivien.destpern Avatar asked Dec 19 '14 14:12

vivien.destpern


People also ask

How do I compare two arrays in Swift?

To check if two arrays are equal in Swift, use Equal To == operator. Equal To operator returns a Boolean value indicating whether two arrays contain the same elements in the same order. If two arrays are equal, then the operator returns true , or else it returns false .


1 Answers

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 

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 

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.

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!).

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 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.

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)      }  } 
like image 179
Airspeed Velocity Avatar answered Sep 18 '22 07:09

Airspeed Velocity