Swift - 确定Array1是否包含Array2中的至少一个对象

时间:2016-05-18 12:17:19

标签: ios arrays swift arraylist

我有2个阵列。比方说,array1 = [1,2,3,4,5]array2 = [2,3]。如果array1包含来自array2的至少一个项目,我该怎么办?

6 个答案:

答案 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)

#1。使用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

#2。使用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]

选项1

a2.filter { a1.contains($0) }.count > 1

选项2

a2.reduce(false, combine: { $0 || a1.contains($1) })

答案 4 :(得分:1)

雨燕5

只需进行扩展

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
    }
}