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

时间:2016-09-28 02:28:54

标签: 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和4位置进行。 5。

理想情况下,我不想用循环迭代数组,我想要类似于array.contains(element)。

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

4 个答案:

答案 0 :(得分: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

答案 1 :(得分:1)

您可以过滤其子序列elementsEqual为true的索引:

extension Collection where Element: Equatable, Index == Int {
    func contains(_ subSequence: SubSequence) -> Bool {
        let size = subSequence.count
        for i in indices.dropLast(size-1) {
            if self[i..<i+size].elementsEqual(subSequence) {
                return true
            }
        }
        return false
    }
}
[1, 2, 3].contains([1, 2])  // true

如果您只需要检查集合是否包含子序列:

KTable

答案 2 :(得分:0)

let firstSeqNum = 5
let secondSeqNum = 9
for (index, number) in array.enumerated() {
    if  number == firstSeqNum && array[index+1] == secondSeqNum {
        print("The sequence \(firstSeqNum), \(secondSeqNum) was found, starting at an index of \(index).")
    }
}

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

答案 3 :(得分:0)

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

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

还有其他变体,例如,您可以在迭代期间继续从piDigits删除第一个字符,并检查piDigits是否以searchedSequence开头。

如果性能至关重要,我建议使用字符串搜索算法,例如Aho-Corasick(见https://en.wikipedia.org/wiki/String_searching_algorithm)首先构建状态机以进行快速比较(类似于正则表达式)。

让我们看看如何使用正则表达式:

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

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