2016-07-13 5 views
2

Я хочу написать расширение для массива, чтобы проверить, содержит ли массив все элементы другого массива, в моем примере использования это строковые объекты, но я продолжаю получать:Проверьте, содержит ли массив все элементы другого в Swift

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

в строке self.contains(item) ошибку в о item

вот мой код:

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 
    } 
} 

ответ

8

Вы необходимо, чтобы элементы последовательности равны Equatable, , но они не связаны с элементами массива. Поэтому

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

не скомпилируется.

То, что вы, вероятно, хотите, чтобы потребовать, чтобы элементы последовательности имеют же тип элементов массива (и это должно быть 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 
    } 
} 

Если вам нужен метод только и не аргументы массива для общих последовательностей, то вы можете упростить декларацию

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

, который может быть сокращен до

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

Как сказал @AMomchilov, делает линейный поиск, так что это имеет O(M*N) сложность, где M и N являются длина двух массивов. Вы могли бы определить специализацию для случая что элементы Hashable и сделать проверку членства против Set:

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

ли это быстрее, чем предыдущий метод или нет, будет зависеть от обоих размеров массива и также по типу элемента (как «дорого» это сравнить элементы).

+0

Примечание к OP: это может быть очень много ускорено, если используется набор. '.contains' выполняет медленный линейный поиск. Это решение в целом имеет квадратичную временную сложность. – Alexander

+1

@AMomchilov: Да (если элементы 'Hashable'). –

+0

@AMomchilov, так что вы предлагаете? – iOSGeek

Смежные вопросы