我有2个阵列。比方说,array1 = [1,2,3,4,5]
和array2 = [2,3]
。如果array1
包含来自array2
的至少一个项目,我该怎么办?
答案 0 :(得分:22)
您只需将array2
的{{3}}函数传入array1
的{{3}}函数(反之亦然),就可以实现此目的,因为您的元素是Equatable
。
let array1 = [2, 3, 4, 5]
let array2 = [20, 15, 2, 7]
// this is just shorthand for array1.contains(where: { array2.contains($0) })
if array1.contains(where: array2.contains) {
print("Array 1 and array 2 share at least one common element")
} else {
print("Array 1 doesn't contains any elements from array 2")
}
这可以通过循环遍历数组1的元素来实现。对于每个元素,它将循环遍历数组2以检查它是否存在于该数组中。如果它找到该元素,它将断开并返回true - 否则为false。
这是有效的,因为实际上有两种contains
。一个接受一个闭包,以便根据自定义谓词检查每个元素,另一个只是直接比较一个元素。在此示例中,array1
正在使用contains
,而array2
正在使用contains
。这就是你可以将contains
函数传递给另一个contains
函数的原因。
虽然,closure version,上述算法是O(n 2 )。一个好的集合交集算法是O(n),因为元素查找是O(1)。因此,如果您的代码对性能至关重要,那么您一定要使用集合来执行此操作(如果您的元素为Hashable
),element version。
虽然如果你想利用contains
给你的早期退出,你会想做这样的事情:
extension Sequence where Iterator.Element : Hashable {
func intersects<S : Sequence>(with sequence: S) -> Bool
where S.Iterator.Element == Iterator.Element
{
let sequenceSet = Set(sequence)
return self.contains(where: sequenceSet.contains)
}
}
的
if array1.intersects(with: array2) {
print("Array 1 and array 2 share at least one common element")
} else {
print("Array 1 doesn't contains any elements from array 2")
}
这与使用数组的contains方法非常相似 - arraySet.contains
方法现在为O(1)的事实存在显着差异。因此整个方法现在将在O(n)处运行(其中n是两个序列的较大长度),可能提前退出。
答案 1 :(得分:9)
另一种方法是使用Set s:
let array1 = [1,2,3,4,5]
let array2 = [2,3]
let set1 = Set(array1)
let intersect = set1.intersect(array2)
if !intersect.isEmpty {
// do something with the intersecting elements
}
答案 2 :(得分:5)
Set
isDisjoint(with:)
方法使用Swift 4,Set
有一个名为isDisjoint(with:)
的方法。 isDisjoint(with:)
有以下声明:
func isDisjoint<S>(with other: S) -> Bool where Int == S.Element, S : Sequence
返回一个布尔值,指示该集合是否没有与给定序列相同的成员。
为了测试两个数组是否没有公共元素,您可以使用使用isDisjoint(with:)
的代码下面的Playground:
let array1 = [1, 3, 6, 18, 24]
let array2 = [50, 100, 200]
let hasNoCommonElement = Set(array1).isDisjoint(with: array2)
print(hasNoCommonElement) // prints: true
Set
intersection(_:)
方法使用Swift 4,Set
有一个名为intersection(_:)
的方法。 intersection(_:)
有以下声明:
func intersection<S>(_ other: S) -> Set<Set.Element> where Element == S.Element, S : Sequence
返回一个新集合,其中包含此集合和给定序列共有的元素。
为了测试两个数组是否有一个或多个公共元素,您可以使用下面使用intersection(_:)
的Playground代码:
let array1 = [1, 3, 6, 18, 24]
let array2 = [2, 3, 18]
let intersection = Set(array1).intersection(array2)
print(intersection) // prints: [18, 3]
let hasCommonElement = !intersection.isEmpty
print(hasCommonElement) // prints: true
答案 3 :(得分:1)
let a1 = [1, 2, 3]
let a2 = [2, 3, 4]
a2.filter { a1.contains($0) }.count > 1
a2.reduce(false, combine: { $0 || a1.contains($1) })
答案 4 :(得分:1)
只需进行扩展
public extension Sequence where Element: Equatable {
func contains(anyOf sequence: [Element]) -> Bool {
return self.filter { sequence.contains($0) }.count > 0
}
}
使用:
let someArray = ["one", "two", "three"]
let string = "onE, Cat, dog"
let intersects = string
.lowercased()
.replacingOccurrences(of: " ", with: "")
.components(separatedBy: ",")
.contains(anyOf: someArray)
print(intersects) // true
答案 5 :(得分:0)
希望这会有所帮助。
//
// Array+CommonElements.swift
//
import Foundation
public extension Array where Element: Hashable {
func set() -> Set<Array.Element> {
return Set(self)
}
func isSubset(of array: Array) -> Bool {
self.set().isSubset(of: array.set())
}
func isSuperset(of array: Array) -> Bool {
self.set().isSuperset(of: array.set())
}
func commonElements(between array: Array) -> Array {
let intersection = self.set().intersection(array.set())
return intersection.map({ $0 })
}
func hasCommonElements(with array: Array) -> Bool {
return self.commonElements(between: array).count >= 1 ? true : false
}
}