在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
答案 0 :(得分: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
。
您可以按如下方式使用它:
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
}
}
}
答案 1 :(得分:3)
据我所知,这样的功能不存在。但您可以添加以下扩展名的功能:
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
答案 2 :(得分: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
}
}
答案 3 :(得分:0)
这个想法可以扩展到所有的等式序列。
public extension Sequence where Element: Equatable {
/// The iterators of all subsequences, incrementally dropping early elements.
/// - Note: Begins with the iterator for the full sequence (dropping zero).
var dropIterators: AnySequence<AnyIterator<Element>> {
.init(
sequence(state: makeIterator()) {
let iterator = $0
return $0.next().map { _ in .init(iterator) }
}
)
}
/// - Note: `false` if `elements` is empty.
func contains<Elements: Sequence>(inOrder elements: Elements) -> Bool
where Elements.Element == Element {
elements.isEmpty
? false
: dropIterators.contains {
AnySequence(zip: ($0, elements))
.first(where: !=)?.1 == nil
}
}
}
public extension Sequence {
/// The first element of the sequence.
/// - Note: `nil` if the sequence is empty.
var first: Element? {
var iterator = makeIterator()
return iterator.next()
}
/// Whether the sequence iterates exactly zero elements.
var isEmpty: Bool { first == nil }
}
public extension AnySequence {
/// Like `zip`, but with `nil` elements for the shorter sequence after it is exhausted.
init<Sequence0: Sequence, Sequence1: Sequence>(
zip zipped: (Sequence0, Sequence1)
) where Element == (Sequence0.Element?, Sequence1.Element?) {
self.init(
sequence(
state: (zipped.0.makeIterator(), zipped.1.makeIterator())
) { iterators in
Optional(
(iterators.0.next(), iterators.1.next())
)
.filter { $0 != nil || $1 != nil }
}
)
}
}
public extension Optional {
/// Transform `.some` into `.none`, if a condition fails.
/// - Parameters:
/// - isSome: The condition that will result in `nil`, when evaluated to `false`.
func filter(_ isSome: (Wrapped) throws -> Bool) rethrows -> Self {
try flatMap { try isSome($0) ? $0 : nil }
}
}
答案 4 :(得分:-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)