2016-05-24 16 views
6

W Swift, w jaki sposób mogę sprawdzić, czy tablica zawiera podarunek w całości? Na przykład, czy istnieje contains funkcja, która działa tak:Tablica zawiera kompletny podplat

let mainArray = ["hello", "world", "it's", "a", "beautiful", "day"] 
contains(mainArray, ["world", "it's"]) // would return true 
contains(mainArray, ["world", "it"]) // would return false 
contains(mainArray, ["world", "a"]) // would return false - not adjacent in mainArray 

Odpowiedz

3

można to zrobić z funkcji wyższego poziomu, tak:

func indexOf(data:[String], _ part:[String]) -> Int? { 
    // This is to prevent construction of a range from zero to negative 
    if part.count > data.count { 
     return nil 
    } 

    // The index of the match could not exceed data.count-part.count 
    return (0...data.count-part.count).indexOf {ind in 
     // Construct a sub-array from current index, 
     // and compare its content to what we are looking for. 
     [String](data[ind..<ind+part.count]) == part 
    } 
} 

ta funkcja zwraca indeks pierwszego meczu, jeśli w ogóle, lub nil otherwi se.

Można go używać w następujący sposób:

let mainArray = ["hello", "world", "it's", "a", "beautiful", "day"] 
if let index = indexOf(mainArray, ["world", "it's"]) { 
    print("Found match at \(index)") 
} else { 
    print("No match") 
} 

edycji w jako rozszerzenie ogólnej tablicy ...

To może być teraz używany dla każdej jednorodnej tablicy Equatable typów.

extension Array where Element : Equatable { 
    func indexOfContiguous(subArray:[Element]) -> Int? { 

     // This is to prevent construction of a range from zero to negative 
     if subArray.count > self.count { 
      return nil 
     } 

     // The index of the match could not exceed data.count-part.count 
     return (0...self.count-subArray.count).indexOf { ind in 
      // Construct a sub-array from current index, 
      // and compare its content to what we are looking for. 
      [Element](self[ind..<ind+subArray.count]) == subArray 
     } 
    } 
} 
+0

Myślę, że to zadziała, ale jest prawdopodobnie zbyt sprytne, aby ludzie mogli je zrozumieć. (To na pewno jest dla mnie). Czy mógłbyś dodać komentarze do tego, aby wyjaśnić, co robi? – Fogmeister

+0

@Fogmeister Pewnie! Jest to o wiele mniej przerażające niż się wydaje - w zasadzie "zmniejszenie" zastępuje pętlę "for" w początkowym indeksie, natomiast "[String] (data [ind .. dasblinkenlight

+0

OK, więc w zasadzie robi ... start od 0. Sprawdź, czy podbardzie na 0 jest równa parametrowi 'part'. Jeśli jest to powrót 0 przez cały czas. Jeśli nie, przejdź do 1 i sprawdź, czy podbarwa o wartości 1 jest równa parametrowi części i tak dalej? – Fogmeister

-2

Tablice nie mają wbudowane funkcje, które szukają, jednak można użyć zestawów, które są przeznaczone do obsługi takich scenariuszy ..

let mainSet:Set = ["hello", "world", "it's", "a", "beautiful", "day"] 
let list2:Set = ["world", "it's"] 
let list3:Set = ["world","a"] 
list2.isSubsetOf(mainSet) 
+3

Twoje podejście błędnie oceni "[" świat "," a "]" jako "podbarwę". –

+0

Tak, oczywiście, aby spełnić ten warunek, prawdopodobnie będziemy musieli użyć niestandardowego predykatu ... – chitnisprasanna

+0

@chitnisprasanna Co masz na myśli przez niestandardowy predykat? Czy mówisz "OK, moje rozwiązanie nie działa, musiałbym to zaprogramować"? Jak rozwiązać ten problem? – Daniel

2

O ile mi wiadomo, taka funkcja nie istnieje. Ale można dodać funkcjonalność z następujących rozszerzeniach:

extension Array where Element: Equatable { 
    func contains(subarray: [Element]) -> Bool { 
     var found = 0 
     for element in self where found < subarray.count { 
      if element == subarray[found] { 
       found += 1 
      } else { 
       found = element == subarray[0] ? 1 : 0 
      } 
     } 

     return found == subarray.count 
    } 
} 

Po rozszerzenie dodaje do swojego projektu, możesz po prostu zadzwonić:

mainArray.contains(["world", "it's"]) // would return true 
mainArray.contains(["world", "it"]) // would return false 
mainArray.contains(["it's", "world"]) // would return false 

let array2 = ["hello", "hello", "world"] 
array2.contains(["hello", "world"]) // would return true 
0

pierwsza próba simpleBob wydaje się pracować przy minimalnej modyfikacji:

extension Array where Element: Equatable { 
    func contains(subarray: [Element]) -> Index? { 
     var found = 0 
     var startIndex:Index = 0 
     for (index, element) in self.enumerate() where found < subarray.count { 
      if element != subarray[found] { 
       found = 0 
      } 
      if element == subarray[found] { 
       if found == 0 { startIndex = index } 
       found += 1 
      } 
     } 

     return found == subarray.count ? startIndex : nil 
    } 
} 
Powiązane problemy