신속한 배열 비교
신속하게 배열을 비교하는 방법을 이해하려고합니다.
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
이 연산자는 lhs
및 의 요소를 반복 rhs
하여 각 위치의 값을 비교합니다. 비트 비교를 수행 하지 않고==
각 요소 쌍에 대해 연산자를 호출합니다 . 즉 ==
, 요소에 대한 사용자 지정 을 작성 하면 호출됩니다.
그러나 여기에는 최적화가 포함되어 있습니다. 두 배열의 기본 버퍼가 같으면 신경 쓰지 않고 참을 반환합니다 (동일한 요소를 포함하고 있습니다. 물론 동일합니다!).
이 문제는 전적으로 NeverEqual
평등 연산자 의 잘못입니다 . 평등은 전이적이고 대칭 적이며 반사적이어야하며 이것은 반사적이지 않습니다 ( x == x
거짓). 그러나 그것은 여전히 당신을 알지 못합니다.
Swift 배열은 copy-on-write입니다. 따라서 쓰기시 var x = y
실제로 배열의 복사본을 만들지 않고 x
의 저장 버퍼 포인터를 y
's에 가리 킵니다 . x
또는 y
나중에 변경되는 경우에만 버퍼의 복사본을 만들어 변경되지 않은 변수에 영향을주지 않습니다. 이는 배열이 값 유형처럼 작동하지만 여전히 성능을 발휘하는 데 중요합니다.
스위프트의 초기 버전에서는, 당신은 실제로 부를 수있는 ===
배열에 (도 초기 버전에서 돌연변이 동작은 돌연변이 경우 비트 다른이 있었다 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
그래서 대답 :
- I think the performance is optimal for doing value (not reference) comparisons
- Yes, if you want to compare values
- Swift arrays are value type and not reference type. So the memory location is the same only if you compare it to itself (or use unsafe pointers)
It depends on how do you want to compare. For example: ["1", "2"] == ["1", "2"] // true
but ["1", "2"] == ["2", "1"] // false
If you need that second case to also be true and are ok with ignoring repetitive values, you can do: Set(["1", "2"]) == Set(["2", "1"]) // true
(use NSSet for Swift 2)
For compare arrays of custom objects we can use 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")
}
Arrays conform to Equatable
in Swift 4.1, negating the caveats mentioned in previous answers. This is available in Xcode 9.3.
https://swift.org/blog/conditional-conformance/
But just because they implemented
==
did not meanArray
orOptional
conformed toEquatable
. Since these types can store non-equatable types, we needed to be able to express that they are equatable only when storing an equatable type.This meant these
==
operators had a big limitation: they couldn’t be used two levels deep.With conditional conformance, we can now fix this. It allows us to write that these types conform to
Equatable
—using the already-defined==
operator—if the types they are based on are equatable.
If you have an array of custom objects, one has to be careful with the equality test, at least with Swift 4.1:
If the custom object is not a subclass of NSObject
, the comparison uses the static func == (lhs: Nsobject, rhs: Nsobject) -> Bool
, which has to be defined.
If it is a subclass of NSObject
, it uses the func isEqual(_ object: Any?) -> Bool
, which has to be overridden.
Please check the following code, and set breakpoints at all return statements.
class Object: Equatable {
static func == (lhs: Object, rhs: Object) -> Bool {
return true
}
}
The following class inheritates Equatable
from NSObject
class Nsobject: NSObject {
static func == (lhs: Nsobject, rhs: Nsobject) -> Bool {
return true
}
override func isEqual(_ object: Any?) -> Bool {
return true
}
}
They can be compared with:
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
참고URL : https://stackoverflow.com/questions/27567736/compare-arrays-in-swift
'code' 카테고리의 다른 글
collections.ChainMap의 목적은 무엇입니까? (0) | 2020.12.08 |
---|---|
SQL Server 2012에서 SQL Server 2014의 백업을 복원 할 수 있습니까? (0) | 2020.12.08 |
JSON.parse가 빈 문자열로 실패하는 이유는 무엇입니까? (0) | 2020.12.08 |
numpy.exp ()는 정확히 무엇을합니까? (0) | 2020.12.08 |
apt-add-repository : Dockerfile에서 명령을 찾을 수 없음 오류 (0) | 2020.12.08 |