数组包含一个完整的子数组

时间:2016-05-24 10:17:06

标签: arrays swift

在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

5 个答案:

答案 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)