Arrays 查找数组中是否存在元素序列

Arrays 查找数组中是否存在元素序列,arrays,swift,Arrays,Swift,是否可以找到数组中是否存在元素序列? 让我们从Pi中取一些数字 let piDigits=[3,1,4,1,5,9,2,6,5,3,5,8,9,7,9,3,2,3,8,4,6,2,6,4,3,3,8,3,2,7,9,5,0,2,8,8,4,1,9,7,1,6,9,3,9,9,3,7,5,1,0,5,8,2,0,9,7,4,9,4,4] 现在,我想找出,5和9是否作为序列元素存在于数组中——在本例中,它们一次存在于位置4和5 理想情况下,我不希望用循环遍历数组,我希望类似于array.con

是否可以找到数组中是否存在元素序列? 让我们从Pi中取一些数字

 let piDigits=[3,1,4,1,5,9,2,6,5,3,5,8,9,7,9,3,2,3,8,4,6,2,6,4,3,3,8,3,2,7,9,5,0,2,8,8,4,1,9,7,1,6,9,3,9,9,3,7,5,1,0,5,8,2,0,9,7,4,9,4,4] 
现在,我想找出,5和9是否作为序列元素存在于数组中——在本例中,它们一次存在于位置4和5

理想情况下,我不希望用循环遍历数组,我希望类似于array.contains(元素)

@Bawpotter,代码片段:

 for element in piDigits{  //check every element
  if element == 5 { //if element is equal with the element i want
    var currentPosition = piDigits.index(of: element) //get the position of that element
    if piDigits[currentPosition!+1] == 9 { //if the element at the next position is equal to the other element i want
        print("true")   // it prints true 7 times, instead of 1!
    }
  }
}

由于没有内置的方法,这将是您最好的选择

在contains方法中,对数组进行迭代,在这里您必须执行相同的操作。这里有一个例子:

extension Array where Element: Equatable {
  func contains(array elements: [Element]) -> Int {
    guard elements.count > 0 else { return 0 }
    guard count > 0 else { return -1 }

    var ti = 0

    for (index, element) in self.enumerated() {
      ti = elements[ti] == element ? ti + 1 : 0

      if ti == elements.count {
        return index - elements.count + 1
      }
    }

    return -1
  }
}
下面是如何使用它:

let index = [1, 4, 5, 6, 6, 9, 6, 8, 10, 3, 4].contains(array: [6, 8, 10])
// index = 6

let index = [1, 4, 5, 6, 6, 9, 6, 8, 10, 3, 4].contains(array: [6, 8, 1])
// index = -1

使用线性搜索的一个非常简单的实现:

let piDigits: [Int] = [3,1,4,1,5,9,2,6,5,3,5,8,9,7,9,3,2,3,8,4,6,2,6,4,3,3,8,3,2,7,9,5,0,2,8,8,4,1,9,7,1,6,9,3,9,9,3,7,5,1,0,5,8,2,0,9,7,4,9,4,4]

let searchedSequence: [Int] = [5, 9]

var index = 0
var resultIndices: [Int] = []

while index < (piDigits.count - searchedSequence.count) {
    let subarray = piDigits[index ..< (index + searchedSequence.count)]

    if subarray.elementsEqual(searchedSequence) {
        resultIndices.append(index)
    }

    index += 1
}

print("Result: \(resultIndices)")

这种方法的缺点是它不会搜索重叠的范围(例如,“592”匹配两个范围,但只报告一个范围)。

您可以在其子序列元素Sequal为真时过滤索引:

extension Collection where Element: Equatable {
    func firstIndex<C: Collection>(of collection: C) -> Index? where C.Element == Element {
        guard !collection.isEmpty else { return nil }
        let size = collection.count
        return indices.dropLast(size-1).first {
            self[$0..<index($0, offsetBy: size)].elementsEqual(collection)
        }
    }
    func indices<C: Collection>(of collection: C) -> [Index] where C.Element == Element {
        guard !collection.isEmpty else { return [] }
        let size = collection.count
        return indices.dropLast(size-1).filter {
            self[$0..<index($0, offsetBy: size)].elementsEqual(collection)
        }
    }
    func range<C: Collection>(of collection: C) -> Range<Index>? where C.Element == Element {
        guard !collection.isEmpty else { return nil }
        let size = collection.count
        var range: Range<Index>!
        guard let _ = indices.dropLast(size-1).first(where: {
            range = $0..<index($0, offsetBy: size)
            return self[range].elementsEqual(collection)
        }) else {
            return nil
        }
        return range
    }
    func ranges<C: Collection>(of collection: C) -> [Range<Index>] where C.Element == Element {
        guard !collection.isEmpty else { return [] }
        let size = collection.count
        return indices.dropLast(size-1).compactMap {
            let range = $0..<index($0, offsetBy: size)
            return self[range].elementsEqual(collection) ? range : nil
        }
    }
}

如果您在swift的标准库中寻找一些东西来实现这一点,我认为没有……如果性能至关重要,您可以使用一些特定的文本搜索算法,例如Aho Corasic。考虑数组是长文本,搜索数组是子字符串。如果性能不重要,我可能会使用一个简单的线性搜索,使用
搜索
。在每个索引上检查下一个
n
项是否与搜索的数组相等,如果是,则输出该索引。谢谢!我玩弄过。列举过,但显然不正确。。我也尝试过:对于piDigits中的元素{if element==5{var currentPosition=piDigits.index(of:element)if piDigits[currentPosition!+1]==9{print(“true”)}},但它不会输出正确的结果,在这种情况下,它会打印true 6次,知道为什么吗?你能编辑你原来的帖子来添加代码吗?格式化后更容易进行故障排除。嗨,Yannick,谢谢你的回答。只要不重复,您的解决方案就可以正常工作。但是如果6,8,10重复两次,它只会给我第一个的位置啊好的,你的问题不清楚。您只需询问“数组中是否存在元素序列”。如果你想拥有所有的序列,你可以在返回的数组中剪切数组,然后重新调用这个方法,直到你拥有所有的序列!我正在尝试进一步制作searchSequence数组,然后将打印结果制作成字典(不要告诉我解决方案,我想自己试试:))我试图找到一个快速版本的aho corasick,但没有成功。@Do2字符串搜索算法库并不多,因为字符串在标准库中已经有了相同的算法。算法的概念仍然有效。将输入转换为字符串,然后搜索正则表达式
(subray1 | subray2 | |…)
的匹配项也是一种方法。很抱歉,我没有得到这一点。。你能给我举个例子吗?@Do2我添加了一个用于搜索子数组的正则表达式的例子。请注意,如果您自己编写算法,则可以控制边缘情况(例如重叠间隔)。
let searchedSequences: [[Int]] = [[5, 9], [7], [9, 2]]

let stringDigits = piDigits.map { String($0) }.joined()
let stringSearchedSequences = searchedSequences.map { sequence in sequence.map { String($0) }.joined() }

let regularExpressionPattern = stringSearchedSequences.joined(separator: "|")

let regularExpression = try! NSRegularExpression(pattern: regularExpressionPattern, options: [])

let matches = regularExpression.matches(in: stringDigits, options: [], range: NSRange(location: 0, length: stringDigits.characters.count))
let matchedIndices = matches.map { $0.range.location }

print("Matches: \(matchedIndices)")
extension Collection where Element: Equatable {
    func firstIndex<C: Collection>(of collection: C) -> Index? where C.Element == Element {
        guard !collection.isEmpty else { return nil }
        let size = collection.count
        return indices.dropLast(size-1).first {
            self[$0..<index($0, offsetBy: size)].elementsEqual(collection)
        }
    }
    func indices<C: Collection>(of collection: C) -> [Index] where C.Element == Element {
        guard !collection.isEmpty else { return [] }
        let size = collection.count
        return indices.dropLast(size-1).filter {
            self[$0..<index($0, offsetBy: size)].elementsEqual(collection)
        }
    }
    func range<C: Collection>(of collection: C) -> Range<Index>? where C.Element == Element {
        guard !collection.isEmpty else { return nil }
        let size = collection.count
        var range: Range<Index>!
        guard let _ = indices.dropLast(size-1).first(where: {
            range = $0..<index($0, offsetBy: size)
            return self[range].elementsEqual(collection)
        }) else {
            return nil
        }
        return range
    }
    func ranges<C: Collection>(of collection: C) -> [Range<Index>] where C.Element == Element {
        guard !collection.isEmpty else { return [] }
        let size = collection.count
        return indices.dropLast(size-1).compactMap {
            let range = $0..<index($0, offsetBy: size)
            return self[range].elementsEqual(collection) ? range : nil
        }
    }
}
[1, 2, 3, 1, 2].indices(of: [1,2])   // [0,3]
[1, 2, 3, 1, 2].ranges(of: [1,2])    // [[0..<2], [3..<5]]
extension Collection where Element: Equatable {
    func contains<C: Collection>(_ collection: C) -> Bool where C.Element == Element  {
        guard !collection.isEmpty else { return false }
        let size = collection.count
        for i in indices.dropLast(size-1) where self[i..<index(i, offsetBy: size)].elementsEqual(collection) {
            return true
        }
        return false
    }
}
[1, 2, 3].contains([1, 2])  // true