如何确定一个数组是否包含Swift中另一个数组的所有元素?

Max*_*tin 33 arrays ios swift

我有2个数组:

var list:Array<Int> = [1,2,3,4,5]
var findList:Array<Int> = [1,3,5]
Run Code Online (Sandbox Code Playgroud)

我想确定listArray是否包含所有findList元素.

顺便说一下,元素也可以String是其他类型.

怎么做?

我知道Swift提供的contains方法适用于一个项目.

ork*_*den 53

您可以使用NSSet为您完成所有工作,而不是遍历数组并自行过滤.

var list:Array<Int> = [1,2,3,4,5]
var findList:Array<Int> = [1,3,5]

let listSet = NSSet(array: list)
let findListSet = NSSet(array: findList)

let allElemtsEqual = findListSet.isSubsetOfSet(otherSet: listSet)
Run Code Online (Sandbox Code Playgroud)

NSSet在检查它是否包含任何对象时比数组快很多.事实上,它就是它的设计目标.

编辑:使用Swift的内置功能Set.

let list = [1,2,3,4,5]
let findList = [1,3,5]
let listSet = Set(list)
let findListSet = Set(findList)

let allElemsContained = findListSet.isSubsetOf(listSet)
Run Code Online (Sandbox Code Playgroud)

  • 你是完全正确的。我再次阅读了该问题,并意识到我误解了该问题,并且使用了错误的方法。正确使用的方法是isSubsetOfSet(_ otherSet :)。谢谢。 (2认同)
  • 这会给出 `let list = [1,2,3,4,5]` 和 `let findList = [1,3,3,5]` 的预期结果吗?当使用 Set 时,findList 是 list 的子集,但在比较数组时则不是。 (2认同)

Max*_*tin 7

考虑以下通用方法:

func arrayContainsArray<S : SequenceType where S.Generator.Element : Equatable>
      (src:S, lookFor:S) -> Bool{

    for v:S.Generator.Element in lookFor{
      if contains(src, v) == false{
        return false
      }
    }
   return true
}
Run Code Online (Sandbox Code Playgroud)

优势 - 方法在第一次失败后停止,不要继续 findList


测试

var listAsInt:Array<Int> = [1,2,3,4,5]
var findListAsInt:Array<Int> = [1,3,5]
var result = arrayContainsArray(listAsInt, findListAsInt) // true
Run Code Online (Sandbox Code Playgroud)
listAsInt:Array<Int> = [1,2,3,4,5]
findListAsInt:Array<Int> = [1,3,5,7,8,9]
result = arrayContainsArray(listAsInt, findListAsInt) // false
Run Code Online (Sandbox Code Playgroud)
var listOfStr:Array<String> = ["aaa","bbb","ccc","ddd","eee"]
var findListOfStr:Array<String> = ["bbb","ccc","eee"]
result = arrayContainsArray(listOfStr, findListOfStr) // true
Run Code Online (Sandbox Code Playgroud)
listOfStr:Array<String> = ["aaa","bbb","ccc","ddd","eee"]
findListOfStr:Array<String> = ["bbb","ccc","eee","sss","fff","ggg"]
result = arrayContainsArray(listOfStr, findListOfStr) // false
Run Code Online (Sandbox Code Playgroud)

(在Beta7上测试过)


Ant*_*nio 6

您可以使用该filter方法返回findList其中不包含的所有元素list:

let notFoundList = findList.filter( { contains(list, $0) == false } )
Run Code Online (Sandbox Code Playgroud)

然后检查返回数组的长度是否为零:

let contained = notFoundList.count == 0
Run Code Online (Sandbox Code Playgroud)

请注意,他的解决方案遍历整个findList数组,因此只要找到不包含的元素,它就不会停止.如果您还想知道哪些元素未包含,则应该使用它.

如果您只需要一个布尔表明是否包含所有元素,那么Maxim Shoustin提供的解决方案更有效.

  • 在 swift 4 你可以这样做: var ts = findList.filter{ !list.contains($0) } (2认同)

Jul*_*ode 6

Swift 3Swift 4中你可以这样写:

extension Array where Element: Equatable {
    func contains(array: [Element]) -> Bool {
        for item in array {
            if !self.contains(item) { return false }
        }
        return true
    }
}
Run Code Online (Sandbox Code Playgroud)

你可以在这里看到contains方法

这只是一个简单的扩展,用于检查您提供的数组是否在当前数组中(self)


Jac*_*kin 6

allSatisfy似乎是您想要的,假设您无法使元素符合Hashable并使用其他人提到的集合交集方法:

let containsAll = array.allSatisfy(otherArray.contains)
Run Code Online (Sandbox Code Playgroud)


Dav*_*mes 5

作为Sequence.contains(element)处理多个元素的补充,请添加以下扩展名:

public extension Sequence where Element : Hashable {
    func contains(_ elements: [Element]) -> Bool {
        return Set(elements).isSubset(of:Set(self))
    }
}
Run Code Online (Sandbox Code Playgroud)

用过的:

list.contains(findList)
Run Code Online (Sandbox Code Playgroud)

由于它使用Set/,Hashable因此其性能比Equatable其他方法好得多。