Reputation: 933
Let's say there are two arrays...
var array1 = ["a", "b", "c"]
var array2 = ["b", "c", "a"]
I'd like the result of the comparison of these two arrays to be true, and the following...
var array1 = ["a", "b", "c"]
var array2 = ["b", "c", "a", "d"]
...to be false. How can I achieve that in Swift? I tried to convert both arrays to sets but for some reason Set() keeps removing some (usually duplicated) objects that the array contains.
Any help would be appreciated.
Upvotes: 81
Views: 87752
Reputation: 11
For determining if an array is a subset of another array, and duplicate elements are not relevant.
public extension Sequence where Element: Equatable {
func contains(allOf sequence: [Element]) -> Bool {
return sequence.allSatisfy { self.contains($0) }
}
}
let a: [Int] = [1, 2, 3, 4]
let b: [Int] = [1, 2, 3]
let c: [Int] = [1, 2, 3, 4, 5]
let d: [Int] = [1, 1, 2, 2, 3, 3, 4, 4]
a.contains(allOf: b) // true
a.contains(allOf: c) // false
a.contains(allOf: d) // true
Upvotes: 0
Reputation: 34245
Swift Compare arrays
input:
let array1 = ["a", "b", "c"]
let array2 = ["b", "c", "a", "c"]
Case 1: Duplicates are important, then use built-in Array.sort()
function which uses Introsort under the hood with O(n log n)
complexity
let array1Sorted = array1.sorted() //a, b, c
let array2Sorted = array2.sorted() //a, b, c, c
if (array1Sorted.count == array2Sorted.count && array1Sorted == array2Sorted) {
//they are identical
}
Case 2: Duplicates are not important - use Set, with O(n)
complexity. The Set
implements Hashable
so the task is to implement the hash function for element
let set1 = Set(array1) //b, c, a
let set2 = Set(array2) //b, c, a
if (set1.count == set2.count && set1 == set2) {
//they are identical
}
Upvotes: 13
Reputation: 31
if I have
array1 = ["x", "y", "z"]
array2 = ["a", "x", "c"]
I can do
array1.filter({array2.contains($0})
to return ["x"]
and likewise
array1.filter({!array2.contains($0)})
to return ["y", "z"]
Upvotes: 1
Reputation: 1269
I know this question is old, and it also didn't want to determine if array1 was a subset of array2. However, This works in Swift 5.3 and Xcode 12.3:
var array1 = ["a", "b", "c"]
var array2 = ["b", "c", "a", "d"]
print("array1 == array2? \(Set(array1) == Set(array2))")
print("array1 subset to array2? \(Set(array1).isSubset(of: Set(array2)))")
Upvotes: 3
Reputation: 146
Swift 5.2 Solution
var array1 = ["a", "b", "c"]
var array2 = ["b", "c", "a"]
if array1.sorted() == array2.sorted() {
print("array 1 & array 2 are same")
}
Upvotes: 11
Reputation: 4521
If elements of your arrays are conforming to Hashable
you can try to use the bag (it's like a set with the registration of each item amount). Here I will use a simplified version of this data structure based on Dictionary
. This extension helps to create bag from array of Hashable
:
extension Array where Element: Hashable {
var asBag: [Element: Int] {
return reduce(into: [:]) {
$0.updateValue(($0[$1] ?? 0) + 1, forKey: $1)
}
}
}
Now you need to generate 2 bags from initial arrays and compare them. I wrapped it in this extension:
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
}
}
}
This solution was tested with Swift 4.2/Xcode 10. If your current Xcode version is prior to 10.0 you can find the function allSatisfy
of ArraySlice
in Xcode9to10Preparation. You can install this library with CocoaPods.
Upvotes: 2
Reputation: 4521
Solution for 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
}
}
The main advantage of this solution is that it uses less memory than other (it always creates just 2 temporary arrays). Also, it does not require for Element
to be Comparable
, just to be Equatable
.
Upvotes: 1
Reputation: 21
Here is a solution that does not require the element to be Comparable
, but only Equatable
. It is much less efficient than the sorting answers, so if your type can be made Comparable, use one of those.
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
}
}
Upvotes: 2
Reputation: 4188
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
Upvotes: 122
Reputation: 11692
Create function to compare them:
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
}
}
Then:
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"]
Upvotes: 2
Reputation: 9226
you can do something like this:
array1.sortInPlace()
array2.sortInPlace()
print(array1,array2)
if array1 == array2 {
print("equal")
} else {
print("not equal")
}
and if don't want change origional array we can do
let sorted1 = array1.sort()
let sorted2 = array2.sort()
if sorted1 == sorted2 {
print("equal")
}else {
print("not equal")
}
Upvotes: 8