繁体   English   中英

在swift中比较数组

[英]Compare arrays in swift

试图了解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在技术上是否使用相同的“内存位置”/指针/等? 我正在了解优化的工作原理和潜在的警告。

谢谢。

你对==有些紧张是正确的:

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

该运算符循环遍历lhsrhs的元素,比较每个位置的值。 没有做按位比较-它调用==每一对元素的操作。 这意味着如果你为你的元素编写一个自定义== ,它就会被调用。

但它包含一个优化 - 如果两个数组的底层缓冲区相同,它不会打扰,它只返回true(它们包含相同的元素,当然它们是相同的!)。

这个问题完全是NeverEqual相等运算符的错。 平等应该是传递的,对称的和反身的,而且这个不是反身的( x == x是假的)。 但它仍然可以抓住你不知不觉。

斯威夫特阵列写入时复制-所以,当你写var x = y它实际上并没有做数组的副本,它只是点x “在s存储缓冲区指针y S”。 只有当xy稍后发生变异时,它才会复制缓冲区,以便未更改的变量不受影响。 这对于数组行为类似于值类型但仍然具有高性能至关重要。

在Swift的早期版本中,你实际上可以在数组上调用=== (同样在早期版本中,变异行为有点不同,如果你突变xy也会改变,即使它已经被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

所以答案是:

  1. 我认为性能是进行价值(非参考)比较的最佳选择
  2. 是的,如果你想比较价值
  3. Swift数组是值类型而不是引用类型。 因此,只有将它与自身进行比较(或使用不安全的指针)时,内存位置才相同

这取决于你想如何比较。 例如: ["1", "2"] == ["1", "2"] // true["1", "2"] == ["2", "1"] // false

如果你需要第二种情况也是如此,并且可以忽略重复值,你可以这样做: Set(["1", "2"]) == Set(["2", "1"]) // true (使用NSSet for Swift 2)

对于自定义对象的比较数组,我们可以使用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")
}

数组符合Swift 4.1中的Equatable ,否定了之前答案中提到的警告。 这在Xcode 9.3中可用。

https://swift.org/blog/conditional-conformance/

但仅仅因为他们实现了==并不意味着Array或者OptionalEquatable 由于这些类型可以存储非等价类型,因此我们需要能够表达它们仅在存储等同类型时才是等同的。

这意味着这些==运算符有一个很大的局限性:它们无法在两个层次上使用。

有条件的一致性,我们现在可以解决这个问题。 它允许我们写这些类型符合Equatable使用已定义的==运算符 - 如果它们所基于的类型是相等的。

如果你有一个自定义对象 数组 ,必须要小心相等测试,至少使用Swift 4.1:
如果自定义对象不是 NSObject的子类,则比较使用static func == (lhs: Nsobject, rhs: Nsobject) -> Bool ,必须定义它。
如果它 NSObject的子类,它使用func isEqual(_ object: Any?) -> Bool ,必须重写它。

请检查以下代码,并在所有返回语句中设置断点。

class Object: Equatable {

    static func == (lhs: Object, rhs: Object) -> Bool {
        return true
    }
}

以下类从NSObject继承Equatable

class Nsobject: NSObject {

    static func == (lhs: Nsobject, rhs: Nsobject) -> Bool {
        return true
    }


    override func isEqual(_ object: Any?) -> Bool {
        return true
    }

}  

他们可以与:

let nsObject1 = Nsobject()
let nsObject2 = Nsobject()
let nsObjectArray1 = [nsObject1]
let nsObjectArray2 = [nsObject2]
let _ = nsObjectArray1 == nsObjectArray2

let object1 = Object()
let object2 = Object()
let objectArray1 = [object1]
let objectArray2 = [object2]
let _ = objectArray1 == objectArray2

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM