2016-05-24 10 views
6

Swiftで配列に指定されたサブアレイが完全に含まれているかどうかを確認する方法はありますか?例えば、このように動作しますcontains機能があります:アレイに完全なサブアレイが含まれています

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 

答えて

3

このようにあなたは、より高いレベルの機能でそれを行うことができます。

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

この機能があれば、最初のマッチのインデックスを返し、またはnil otherwi se。

次のようにあなたはそれを使用することができます。一般的な配列への拡張としてで

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

編集...

これは今Equatable種類のいずれかの均質な配列のために使用することができます。

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

これはうまくいくと思いますが、人々が理解するにはあまりにも賢いかもしれません。 (それは確かに私のためです)。あなたはそれが何をしているのかを説明するためにこれにいくつかのコメントを追加することができますか? – Fogmeister

+0

@Fogmeisterよろしく!基本的には、初期インデックスの "for"ループを "reduce"に置き換え、 '[String](data [ind .. dasblinkenlight

+0

OKですので、基本的には0で始まります。0の部分配列が 'part'パラメータと等しいことを確認してください。それがすべて0を返すならば。 1になっていない場合、部分配列が1であることを部分パラメータと同じようにチェックするなどですか? – Fogmeister

-2

配列は、あなたが探している作り付けの機能を持っていない、しかし、あなたはこのようなシナリオを処理するように設計されているセットを使用することができます。..

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

あなたのアプローチは誤って '[" world "、" a "]'を "サブアレイ"として評価します。 –

+0

もちろん、その条件を満たすために、カスタム述語を使用する必要があるかもしれません... – chitnisprasanna

+0

@chitnisprasannaカスタム述語はどういう意味ですか? "OK私の解決策は機能しません、私はこれをプログラムする必要があります"と言っていますか?これをどうやって解決しますか? – Daniel

2

私の知る限り、そのような機能は存在しません。しかし、あなたは以下の拡張子を持つ機能を追加することができます:拡張子がプロジェクトに追加されたら

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

、あなただけ呼び出すことができます。

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の最初の試みは、最小限の変更で動作するように思わ

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 
    } 
} 
関連する問題