Check if an array contains all elements of another in Swift

别说谁变了你拦得住时间么 提交于 2019-12-22 12:23:50

问题


I want to write an extension for array to check if an array contains all the elements of another array, in my use case it's string objects but I keep get:

Cannot convert value of type 'T.Generator.Element' to expected argument type '@noescape _ throws -> Bool'

in the line self.contains(item) the error in about item

here is my code:

extension Array {
    func containsArray<T : SequenceType where T.Generator.Element : Equatable> (array:T) -> Bool{
        for item:T.Generator.Element in array{
            if !self.contains(item) {
                return false
            }
        }
        return true
    }
}

回答1:


You have required that the sequence elements are Equatable, but they are unrelated to the array elements. Therefore

 if !self.contains(item) { ... }

does not compile.

What you probably want is to require that the sequence elements have the same type as the array elements (and that should be Equatable):

extension Array where Element: Equatable {
    func containsArray<T : SequenceType where T.Generator.Element == Element> (array:T) -> Bool {
        for item in array {
            if !self.contains(item) {
                return false
            }
        }
        return true
    }
}

If you need the method for array arguments only and not for general sequences then you can simplify the declaration to

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

which can be shortened to

extension Array where Element: Equatable {
    func containsArray(array: [Element]) -> Bool {
        return !array.contains { !self.contains($0) }
    }
}

As @AMomchilov said, contains() does a linear search, so this has O(M*N) complexity where M and N are the length of the two arrays. You could define a specialization for the case that the elements are Hashable, and do the membership check against a Set:

extension Array where Element: Hashable {
    func containsArray(array: [Element]) -> Bool {
        let selfSet = Set(self)
        return !array.contains { !selfSet.contains($0) }
    }
}

Whether this is faster than the previous method or not would depend on both array sizes and also on the element type (how "expensive" is it to compare elements).



来源:https://stackoverflow.com/questions/38361574/check-if-an-array-contains-all-elements-of-another-in-swift

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