In Swift how can I check whether an array contains a given subarray in its entirety? E.g., 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
You can do it with higher-level functions, like this:
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 in as an extension to a generic array...
This can now be used for any homogeneous 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
}
}
}
As far as I know, such a function does not exist. But you can add the functionality with following extension:
extension Array where Element: Equatable {
func contains(subarray: [Element]) -> Bool {
guard subarray.count <= count else { return false }
for idx in 0 ... count - subarray.count {
let start = index(startIndex, offsetBy: idx)
let end = index(start, offsetBy: subarray.count)
if Array(self[start ..< end]) == subarray { return true }
}
return false
}
}
Once the extension is added to your project, you can just call:
mainArray.contains(["world", "it's"]) // true
mainArray.contains(["world", "it"]) // false
mainArray.contains(["it's", "world"]) // false
let array2 = ["hello", "hello", "world"]
array2.contains(["hello", "world"]) // true
[1, 1, 1, 2].contains(subarray: [1, 1, 2]) // true
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With