假设有两个数组...
var array1 = ["a", "b", "c"]
var array2 = ["b", "c", "a"]
我希望这两个数组的比较结果为真,下面...
var array1 = ["a", "b", "c"]
var array2 = ["b", "c", "a", "d"]
……假的。我怎样才能在 Swift 中做到这一点?我试图将两个数组都转换为集合,但由于某种原因 Set() 不断删除数组包含的一些(通常是重复的)对象。
任何帮助将不胜感激。
斯威夫特 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
使用集合快速比较数组
let array1 = ["a", "b", "c"]
let array2 = ["b", "c", "a", "c"]
let set1 = Set(array1)
let set2 = Set(array2)
if (set1.count == set2.count && set1 == set2) { //if you compare big sets it is recommended to compare the count of items in the sets beforehand
//they are identical
}
Set
实现 Hashable
所以任务是实现哈希函数以与 Set
一起工作
请注意,如果重复项对您很重要,则此方法不适合
你可以这样做:
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")
}
Swift 5.2 解决方案
var array1 = ["a", "b", "c"]
var array2 = ["b", "c", "a"]
if array1.sorted() == array2.sorted() {
print("array 1 & array 2 are same")
}
我知道这个问题很老了,它也不想确定array1是否是array2的子集。然而,这适用于 Swift 5.3 和 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)))")
创建比较它们的函数:
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,您可以在
Xcode9to10Preparation中找到
allSatisfy
的ArraySlice
函数。您可以使用 CocoaPods 安装此库。
如果我有
array1 = ["x", "y", "z"]
array2 = ["a", "x", "c"]
我能行
array1.filter({array2.contains($0})
返回
["x"]
同样
array1.filter({!array2.contains($0)})
返回
["y", "z"]