How to determine if one array contains all elements of another array in Swift?

匿名 (未验证) 提交于 2019-12-03 02:20:02

问题:

I have 2 arrays:

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

I want to determine if list Array contains all findList elements.

By the way, elements might be String as well or other type.

How to do that?

I know that Swift provides contains method that works with one item.

回答1:

Instead of iterating through arrays and doing filtering yourself, you can use NSSet to do all the work for you.

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)

NSSet is a lot faster than arrays at checking if it contains any object. In fact it's what it's designed for.

Edit: Using Swift's built-in 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)


回答2:

Consider following generic method:

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 }

The advantage - method stops after 1st fail and do not continue over findList


Tests

var listAsInt:Array<Int> = [1,2,3,4,5] var findListAsInt:Array<Int> = [1,3,5] var result = arrayContainsArray(listAsInt, findListAsInt) // true

listAsInt:Array<Int> = [1,2,3,4,5] findListAsInt:Array<Int> = [1,3,5,7,8,9] result = arrayContainsArray(listAsInt, findListAsInt) // false

var listOfStr:Array<String> = ["aaa","bbb","ccc","ddd","eee"] var findListOfStr:Array<String> = ["bbb","ccc","eee"] result = arrayContainsArray(listOfStr, findListOfStr) // true

listOfStr:Array<String> = ["aaa","bbb","ccc","ddd","eee"] findListOfStr:Array<String> = ["bbb","ccc","eee","sss","fff","ggg"] result = arrayContainsArray(listOfStr, findListOfStr) // false

(tested on Beta7)



回答3:

You can use the filter method to return all elements of findList which are not in list:

let notFoundList = findList.filter( { contains(list, $0) == false } )

then check if the length of the returned array is zero:

let contained = notFoundList.count == 0

Note that his solution traverses the entire findList array, so it doesn't stop as soon as a non contained element is found. It should be used if you also want to know which elements are not contained.

If you just need a boolean stating whether all elements are contained or not, then the solution provided by Maxim Shoustin is more efficient.



回答4:

In Swift 3 you can write this:

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

You can see the contains method here

This is just a simple extension that check if the array that you give is in the current array (self)



回答5:

Right now, I'd probably use something like:

let result = list.reduce(true, { $0 ? contains(findList, $1) : $0 })

...but then I did just read this article, which might be biasing me towards this kind of solution. You could probably make this more efficient without making it completely unreadable, but it's early and I've not had my coffee.



回答6:

Extend the Array with the following methods:

extension Array {      func contains<T where T : Equatable>(obj: T) -> Bool {         return self.filter({$0 as? T == obj}).count > 0     }      func isEqualTo< T : Equatable> (comparingArray : [T]) -> Bool {          if self.count != comparingArray.count {             return false         }          for e in comparingArray {             if !self.contains(e){                 return false             }         }          return true     } }

An example of how you can use it like this:

if selectedDates.isEqualTo(originalDates) {     //Arrays the same hide save button } else {     //Arrays not the same, show Save & Discard Changes Button (if not shown) }

Shout out to @David Berry for the contain method.



回答7:

This is Maxim Shoustin's answer updated for Swift 3:

func arrayContainsArray<S : Sequence>     (src:S, lookFor:S) -> Bool where S.Iterator.Element : Equatable{      for v:S.Iterator.Element in lookFor{         if src.contains(v) == false{             return false         }     }     return true }


回答8:

As a complement to Sequence.contains(element) handling multiple elements, add this extension:

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

Used:

list.contains(findList)

Since this uses Set/Hashable it performs much better than Equatable alternatives.



回答9:

var check = true  for i in findList {     if list.contains(i) {         check = check && true     } else {         check = false     } }

This works perfectly fine, as long as, the use of .operator is not required.



标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!