2016-05-24 12 views
6

In Swift wie kann ich überprüfen, ob ein Array ein bestimmtes Subarray in seiner Gesamtheit enthält? Zum Beispiel gibt es eine contains Funktion, die wie folgt funktioniert:Array enthält ein komplettes Subarray

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 

Antwort

3

Sie können es mit Funktionen höherer Ebene tun, wie folgt aus:

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

diese Funktion gibt den Index des ersten Spiels, falls vorhanden, oder nil otherwi se.

Sie können es wie folgt:

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

Schnitt in als Erweiterung zu einer generischen Array ...

Dies kann nun für jede homogene Anordnung von Equatable Typen verwendet werden.

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

Ich denke, das würde funktionieren, ist aber möglicherweise zu schlau für die Leute zu verstehen. (Es ist sicherlich für mich). Könnten Sie dem bitte einige Kommentare hinzufügen, um zu erklären, was es tut? – Fogmeister

+0

@Fogmeister Sicher! Das ist viel weniger beängstigend als es aussieht, aber im Grunde ersetzt "reduce" eine "for" -Schleife im ursprünglichen Index, während '[String] (data [ind .. dasblinkenlight

+0

OK, so dass es im Grunde ... bei 0 beginnt. Überprüfen Sie, ob das Subarray bei 0 dem 'part' Parameter entspricht. Wenn es 0 zurückgibt, bis zum Ende. Wenn nicht, gehe zu 1 und überprüfe, ob das Unterfeld bei 1 gleich dem Teileparameter ist und so weiter? – Fogmeister

-2

Arrays nicht über die eingebauten Funktionen, die Sie suchen, jedoch können Sie Gruppen verwenden, die solche Szenarien zu behandeln sind so konzipiert, ..

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

Ihr Ansatz würde fälschlicherweise '[" world "," a "]' als "Subarray" auswerten. –

+0

Ja, natürlich, um diese Bedingung zu erfüllen, müssen wir möglicherweise benutzerdefinierte Prädikat verwenden ... – chitnisprasanna

+0

@chitnisprasanna Was meinst du mit benutzerdefinierten Prädikat? Sagen Sie "OK, meine Lösung funktioniert nicht, ich müsste das programmieren"? Wie würdest du das lösen? – Daniel

2

Soweit ich weiß, existiert eine solche Funktion nicht. Aber man kann die Funktionalität mit folgenden Erweiterung hinzufügen:

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

Sobald die Erweiterung zu einem Projekt hinzugefügt wird, können Sie rufen Sie einfach an:

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

simpleBob erster Versuch scheint mit einer minimalen Änderung zu arbeiten:

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