试图了解swift如何比较数组.
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表示阵列副本背后有优化措施.看起来有时 - 并不总是 - 结构实际上是复制或不复制.
那说,
1)是= =迭代所有数组以执行基于元素的比较?(看起来像这样) - >那么非常大的阵列上的性能/内存使用情况呢?
2)如果所有元素相等,我们是否确定==将会返回true?我对Java Strings的==有不好的回忆
3)有没有办法检查myArray1和myArray2在技术上是否使用相同的"内存位置"/指针/等?我正在了解优化的工作原理和潜在的警告.
谢谢.
对于比较自定义对象的数组,我们可以使用elementsEqual。
class Person { let ID: Int! let name: String! init(ID: Int, name: String) { self.ID = ID self.name = name } } let oldFolks = [Person(ID: 1, name: "Ann"), Person(ID: 2, name: "Tony")] let newFolks = [Person(ID: 2, name: "Tony"), Person(ID: 4, name: "Alice")] if oldFolks.elementsEqual(newFolks, by: { $0.ID == $1.ID }) { print("Same people in same order") } else { print("Nope") }
你有点紧张==
:
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
,但它们确实有一个==
运算符,在标准库中定义为:
func ==<T : Equatable>(lhs: [T], rhs: [T]) -> Bool
该运算符循环遍历元素,lhs
并rhs
比较每个位置的值.它不是做一个按位比较-它调用==
的每个元素对运营商.这意味着如果你==
为你的元素编写一个自定义,它就会被调用.
但它包含一个优化 - 如果两个数组的底层缓冲区相同,它不会打扰,它只返回true(它们包含相同的元素,当然它们是相同的!).
这个问题完全是NeverEqual
等于运算符的错.平等应该是传递的,对称的和反身的,而这个不是反身的(x == x
是假的).但它仍然可以抓住你不知不觉.
Swift数组是写时复制的 - 因此当你编写var x = y
它时实际上并没有复制数组,它只是将x
存储缓冲区指针指向y
.只有在以后发生变异x
或y
变异时,它才会复制缓冲区,以便未更改的变量不受影响.这对于数组行为类似于值类型但仍然具有高性能至关重要.
在Swift的早期版本中,你实际上可以调用===
数组(同样在早期版本中,变异行为有点不同,如果你发生了变异x
,y
即使它已被声明也会改变let
- 这让人们感到害怕,所以他们改变了它) .
你可以===
用这种方式重现数组上的旧行为(非常依赖于实现,除了戳戳和刺激调查之外不依赖于它)技巧:
let a = [1,2,3] var b = a a.withUnsafeBufferPointer { outer in b.withUnsafeBufferPointer { inner in println(inner.baseAddress == outer.baseAddress) } }
==
在Swift中与Java相同equals()
,它比较了值.
===
在Swift中与Java相同==
,它比较了引用.
在Swift中,您可以像这样简单地比较数组内容值:
["1", "2"] == ["1", "2"]
但是如果你想比较引用,这将不起作用:
var myArray1 = [NSString(string: "1")] var myArray2 = [NSString(string: "1")] myArray1[0] === myArray2[0] // false myArray1[0] == myArray2[0] // true
所以答案是:
我认为性能是进行价值(非参考)比较的最佳选择
是的,如果你想比较价值
Swift数组是值类型而不是引用类型.因此,只有将它与自身进行比较(或使用不安全的指针)时,内存位置才相同
这取决于你想如何比较.例如:
["1", "2"] == ["1", "2"] // true
但是
["1", "2"] == ["2", "1"] // false
如果你需要第二种情况也是如此,并且可以忽略重复值,你可以这样做:(
Set(["1", "2"]) == Set(["2", "1"]) // true
使用NSSet for Swift 2)