【问题标题】:Swift - Determine if Array1 contains at least one object from Array2Swift - 确定 Array1 是否至少包含一个来自 Array2 的对象
【发布时间】:2016-09-14 22:14:31
【问题描述】:

我有 2 个数组。比如array1 = [1,2,3,4,5]array2 = [2,3]。如果array1 至少包含array2 中的一项,我该如何快速签入?

【问题讨论】:

标签: ios arrays swift arraylist


【解决方案1】:

您只需将array2contains 函数传入array1contains 函数(反之亦然)即可,因为您的元素是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 使用 closure versionarray2 使用 element version。这就是您可以将contains 函数传递给另一个contains 函数的原因。


虽然如correctly pointed out by @AMomchilov,上述算法是O(n2)。一个好的集合交集算法是 O(n),因为元素查找是 O(1)。因此,如果您的代码对性能至关重要,那么您绝对应该使用集合来执行此操作(如果您的元素是 Hashable),as shown by @simpleBob

虽然如果你想利用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 是两个序列的较大长度),并有可能提前退出。

【讨论】:

  • 简单最好的解决方案!
  • @iOS 乐于助人:)
  • 能否包含指向 contains 函数的一些文档的链接?谢谢。
  • @Arc676 在我的第三段中,我有指向the closureelement contains 函数的链接——不过我会在第一段中添加一个链接:)
  • 那么不同的 2 个对象列表,至少包含一个属性如何?这个答案只是相同的两个对象列表。我坚持这一点。哈哈
【解决方案2】:

另一种方法是使用Sets:

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
}

【讨论】:

  • 这可能是最好的方法。 O(n) 与 O(n^2)
【解决方案3】:

使用 Swift 5,您可以使用以下路径之一来查找两个数组是否具有共同元素。


#1。使用SetisDisjoint(with:)方法

Set 有一个名为isDisjoint(with:) 的方法。 isDisjoint(with:) 有以下声明:

func isDisjoint(with other: Set<Element>) -> Bool

返回一个布尔值,指示该集合是否没有与给定序列相同的成员。

为了测试两个数组是否没有共同元素,可以使用下面实现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。使用Setintersection(_:)方法

Set 有一个名为intersection(_:) 的方法。 intersection(_:) 有以下声明:

func intersection<S>(_ other: S) -> 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

【讨论】:

  • 我很高兴得到真正了解这些东西的人(不是我)的确认,但我想isDisjoint(with:)!intersection.isEmpty 更高效?
【解决方案4】:

斯威夫特 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】:
    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) })
    

    【讨论】:

      【解决方案6】:

      希望这会有所帮助。

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

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2018-03-21
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2018-08-11
        • 1970-01-01
        相关资源
        最近更新 更多