2つの配列があるとしましょう...
var array1 = ["a", "b", "c"]
var array2 = ["b", "c", "a"]
これら2つの配列の比較の結果が真であり、次のことを望んでいます...
var array1 = ["a", "b", "c"]
var array2 = ["b", "c", "a", "d"]
...虚偽である。 Swiftでそれをどのように達成できますか?両方の配列をセットに変換しようとしましたが、何らかの理由でSet()が配列に含まれる(通常は複製された)オブジェクトを削除し続けます。
任意の助けをいただければ幸いです。
Swift 3、4
extension Array where Element: Comparable {
func containsSameElements(as other: [Element]) -> Bool {
return self.count == other.count && self.sorted() == other.sorted()
}
}
// usage
let a: [Int] = [1, 2, 3, 3, 3]
let b: [Int] = [1, 3, 3, 3, 2]
let c: [Int] = [1, 2, 2, 3, 3, 3]
print(a.containsSameElements(as: b)) // true
print(a.containsSameElements(as: c)) // false
次のようなことができます:
array1.sortInPlace()
array2.sortInPlace()
print(array1,array2)
if array1 == array2 {
print("equal")
} else {
print("not equal")
}
元の配列を変更したくない場合は、
let sorted1 = array1.sort()
let sorted2 = array2.sort()
if sorted1 == sorted2 {
print("equal")
}else {
print("not equal")
}
それらを比較する関数を作成します。
func containSameElements(var firstArray firstArray: [String], var secondArray: [String]) -> Bool {
if firstArray.count != secondArray.count {
return false
} else {
firstArray.sortInPlace()
secondArray.sortInPlace()
return firstArray == secondArray
}
}
次に:
var array1 = ["a", "a", "b"]
var array2 = ["a", "b", "a"]
var array3 = ["a", "b", "c"]
var array4 = ["b", "c", "a", "d"]
print(containSameElements(firstArray: array1, secondArray: array2)) //true
print(containSameElements(firstArray: array3, secondArray: array4)) //false
print(array1) //["a", "a", "b"]
print(array2) //["a", "b", "a"]
print(array3) //["a", "b", "c"]
print(array4) //["b", "c", "a", "d"]
以下は、要素がComparable
である必要はなく、Equatable
のみであるソリューションです。ソートの答えよりもはるかに効率が悪いため、タイプを比較可能にできる場合は、それらのいずれかを使用してください。
extension Array where Element: Equatable {
func equalContents(to other: [Element]) -> Bool {
guard self.count == other.count else {return false}
for e in self{
guard self.filter{$0==e}.count == other.filter{$0==e}.count else {
return false
}
}
return true
}
}
Swift 4.1/Xcode 9.4:
extension Array where Element: Equatable {
func containSameElements(_ array: [Element]) -> Bool {
var selfCopy = self
var secondArrayCopy = array
while let currentItem = selfCopy.popLast() {
if let indexOfCurrentItem = secondArrayCopy.index(of: currentItem) {
secondArrayCopy.remove(at: indexOfCurrentItem)
} else {
return false
}
}
return secondArrayCopy.isEmpty
}
}
このソリューションの主な利点は、他よりも少ないメモリを使用することです(常に2つの一時配列のみを作成します)。また、Element
がComparable
である必要はなく、Equatable
である必要があります。
配列の要素がHashable
に準拠している場合、バッグを使用してみることができます(各アイテムの量を登録したセットのようなものです)。ここでは、Dictionary
に基づいたこのデータ構造の簡易バージョンを使用します。この拡張機能は、Hashable
の配列からバッグを作成するのに役立ちます。
extension Array where Element: Hashable {
var asBag: [Element: Int] {
return reduce(into: [:]) {
$0.updateValue(($0[$1] ?? 0) + 1, forKey: $1)
}
}
}
次に、初期配列から2つのバッグを生成し、それらを比較する必要があります。この拡張機能でラップしました。
extension Array where Element: Hashable {
func containSameElements(_ array: [Element]) -> Bool {
let selfAsBag = asBag
let arrayAsBag = array.asBag
return selfAsBag.count == arrayAsBag.count && selfAsBag.allSatisfy {
arrayAsBag[$0.key] == $0.value
}
}
}
このソリューションは、Swift 4.2/Xcode 10でテストされました。現在のXcodeバージョンが10.0より前の場合、allSatisfy
of ArraySlice
の関数を見つけることができます- Xcode9to10Preparation 。CocoaPodsでこのライブラリをインストールできます。
Set
を使用する
var array1 = ["a", "b", "c"]
var array2 = ["b", "c", "a"]
if (Set(array1) == Set(array2)) {
//they are identical
}
Set
はHashable
を実装するため、タスクはSet
で動作するハッシュ関数を実装することです