Array contains full subarray

In Swift, how can I check if an array contains a given subarray as a whole? For example, is there a contains function that works like this:

 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 
+6
source share
4 answers

You can do this with higher level functions, for example:

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

This function returns the index of the first match, if any, or nil otherwise.

You can use it as follows:

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

Editing as an extension for a shared array ...

Now it can be used for any uniform array of Equatable types.

 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 } } } 
+3
source

As far as I know, such a function does not exist. But you can add functionality with the following extension:

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

Once the add is added to your project, you can simply call:

 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 
+2
source

simpleBob first attempt seems to work with minimal modification:

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

Arrays do not have the built-in capabilities that you are looking for, however you can use sets designed to handle such scenarios.

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

All Articles