¿Cómo determinar si una matriz contiene todos los elementos de otra matriz en Swift?

Tengo 2 matrices:

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

Deseo determinar si la matriz de list contiene todos los elementos findList .

Por cierto, los elementos pueden ser String también u otro tipo.

¿Como hacer eso?

Sé que Swift proporciona el método que funciona con un elemento.

En lugar de recorrer iteraciones a través de matrices y filtrarse usted mismo, puede usar NSSet para hacer todo el trabajo por usted.

 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 es mucho más rápido que las matrices al comprobar si contiene algún object. De hecho, es para lo que está diseñado.

Editar: usando el set incorporado de Swift.

 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) 

Considere el siguiente método genérico:

 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 } 

La ventaja: el método se detiene después de la primera falla y no continúa por encima de la list de findList


Pruebas

 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 

(probado en Beta7)

Puede usar el método de filter para devolver todos los elementos de findList que no están en la list :

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

luego verifique si la longitud de la matriz devuelta es cero:

 let contained = notFoundList.count == 0 

Tenga en count que su solución atraviesa toda la matriz findList , por lo que no se detiene tan pronto como se encuentre un elemento no contenido. Debería usarse si también quiere saber qué elementos no están contenidos.

Si solo necesita un boolean que indique si todos los elementos están contenidos o no, entonces la solución provista por Maxim Shoustin es más eficiente.

En este momento, probablemente use algo como:

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

… pero luego acabo de leer este artículo , lo que podría estar inclinándome hacia este tipo de solución. Probablemente podría hacer esto más eficiente sin hacerlo completamente ilegible, pero es temprano y no he tomado mi café.

En Swift 3 puedes escribir esto:

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

Puedes ver el método contiene aquí.

Esta es solo una extensión simple que comtesting si la matriz que das está en la matriz actual (self)

Amplíe la Array con los siguientes 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 } } 

Un ejemplo de cómo puede usarlo así:

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

Grita a @David Berry por el método contain .

Esta es la respuesta de Maxim Shoustin actualizada para 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 } 
 var check = true for i in findList { if list.contains(i) { check = check && true } else { check = false } } 

Esto funciona perfectamente bien, siempre y cuando no se requiera el uso de .operator.