Ios 如何确定Swift中一个数组是否包含另一个数组的所有元素?
我有两个阵列:Ios 如何确定Swift中一个数组是否包含另一个数组的所有元素?,ios,arrays,swift,Ios,Arrays,Swift,我有两个阵列: var list:Array<Int> = [1,2,3,4,5] var findList:Array<Int> = [1,3,5] var列表:数组=[1,2,3,4,5] var findList:Array=[1,3,5] 我想确定list数组是否包含所有findList元素 顺便说一下,元素可能是String或其他类型 怎么做 我知道Swift提供了包含方法,可用于一个项目。考虑以下通用方法: func arrayContainsArray&
var list:Array<Int> = [1,2,3,4,5]
var findList:Array<Int> = [1,3,5]
var列表:数组=[1,2,3,4,5]
var findList:Array=[1,3,5]
我想确定list
数组是否包含所有findList
元素
顺便说一下,元素可能是String
或其他类型
怎么做
我知道Swift提供了
包含方法,可用于一个项目。考虑以下通用方法:
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
}
listAsInt:Array=[1,2,3,4,5]
findlistaint:Array=[1,3,5,7,8,9]
结果=ArrayContainesArray(listAsInt,findListAsInt)//false
var-listOfStr:Array=[“aaa”、“bbb”、“ccc”、“ddd”、“eee”]
var findListOfStr:Array=[“bbb”、“ccc”、“eee”]
结果=ArrayContainesArray(listOfStr,findListOfStr)//true
listOfStr:Array=[“aaa”、“bbb”、“ccc”、“ddd”、“eee”]
findListOfStr:Array=[“bbb”、“ccc”、“eee”、“sss”、“fff”、“ggg”]
结果=ArrayContainesArray(listOfStr,findListOfStr)//false
(在Beta7上测试)现在,我可能会使用以下内容:
let result = list.reduce(true, { $0 ? contains(findList, $1) : $0 })
…但后来我就这么做了,这可能会使我倾向于这种解决方案。您可以在不使其完全不可读的情况下使其更有效,但时间还早,而且我还没有喝过咖啡。您可以使用过滤器
方法返回查找列表
中不在列表
中的所有元素:
let notFoundList = findList.filter( { contains(list, $0) == false } )
然后检查返回数组的长度是否为零:
let contained = notFoundList.count == 0
请注意,他的解决方案遍历整个findList
数组,因此它不会在找到不包含的元素时立即停止。如果您还想知道哪些元素未包含,则应该使用它
如果您只需要一个布尔值来说明是否包含所有元素,那么Maxim Shoustin提供的解决方案效率更高。您可以使用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)
使用以下方法扩展数组
:
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
}
}
向@David Berry大声喊出方法 这是对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
}
func数组内容数组
(src:S,lookFor:S)->Bool其中S.Iterator.Element:equalable{
对于lookFor中的v:S.Iterator.Element{
如果src.包含(v)=false{
返回错误
}
}
返回真值
}
在Swift 3或Swift 4中,您可以编写以下内容:
extension Array where Element: Equatable {
func contains(array: [Element]) -> Bool {
for item in array {
if !self.contains(item) { return false }
}
return true
}
}
您可以看到contains方法
这只是一个简单的扩展,用于检查您提供的数组是否在当前数组(self)中,作为对序列的补充。包含(element)
处理多个元素,请添加此扩展:
public extension Sequence where Element : Hashable {
func contains(_ elements: [Element]) -> Bool {
return Set(elements).isSubset(of:Set(self))
}
}
使用:
因为它使用了Set
/Hashable
方法,所以它的性能比equalable
方法要好得多。前面的答案似乎都不正确
考虑:
let a = [2,2]
let b = [1,2,3]
我们不会说b实际上“包含”a,但如果您的算法基于for-loop&swift的内置contains(element:)
或一个集合,则上述情况将通过。似乎是您想要的,假设您无法将您的元素与Hashable
一致,并使用其他人提到的集合交集方法:
let containsAll = subArray.allSatisfy(largerArray.contains)
如果需要确定,则一个阵列是另一个阵列的子阵列
公共扩展数组,其中元素:equalable{
func isSuperArray(属于数组:数组)->Bool{
警卫
count>=array.count,
让index=array.first.flatMap(索引(of:),
!index.isEmpty else{
返回错误
}
让arraysForComparison=索引
.compactMap{index->[Element]?在
保护索引+(array.count-1)[索引]{
枚举()
.filter{element==0.1}
.map{index,{in index}
}
}
用法示例:
让数组1=[1,2,3,4]
设array2=[2,3]
打印(array1.isSuperArray(of:array2))//true
print(array2.issubray(of:array1))//true
打印(array2.isSuperArray(of:array1))//false
打印(array1.issubray(of:array2))//false
我自己使用这组扩展方法。我希望这段代码有助于:
// 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
}
}
//数组+CommonElements.swift
进口基金会
公共扩展数组,其中元素:可哈希{
func set()->set{
返回集(自身)
}
func isSubset(属于数组:数组)->Bool{
self.set().isSubset(of:array.set())
}
func isSuperset(数组的名称:数组)->Bool{
self.set()
}
func commonElements(数组之间:数组)->array{
让交点=self.set().intersection(array.set())
返回intersection.map({$0})
}
func hasCommonElements(带数组:array)->Bool{
返回self.commonElements(介于:数组之间)。计数>=1?true:false
}
}
这两个集合如何相等?据我所知,这只是从每个数组生成一个唯一的集合,然后对它们进行比较?这些集合是相等的。它们不一样。listSet==findListSet
是错误的。你完全正确。我再次阅读了这个问题,意识到我误解了它,使用了错误的方法正确的使用方法是isSubsetOfSet(u.otherSet:)
。谢谢。您现在可以使用Swift的内置集类型进行此操作。这会给出let list=[1,2,3,4,5]
和let findList=[1,3,3,5]的预期结果吗
?当使用Set
时,findList
是列表的一个子集,但不仅仅是在比较数组时。我尝试在Playdool中测试这一点…在这一行“if contains(src,v)=false{”。我得到错误“contains不可用:调用序列上的contains()方法”有什么想法吗?注意,有几个答案建议使用equalatable
一致性解决方案,这会产生>=O(n)性能
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
}
extension Array where Element: Equatable {
func contains(array: [Element]) -> Bool {
for item in array {
if !self.contains(item) { return false }
}
return true
}
}
public extension Sequence where Element : Hashable {
func contains(_ elements: [Element]) -> Bool {
return Set(elements).isSubset(of:Set(self))
}
}
list.contains(findList)
let a = [2,2]
let b = [1,2,3]
let containsAll = subArray.allSatisfy(largerArray.contains)
// 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
}
}