在矩阵中查找下一个元素

时间:2019-02-26 11:10:53

标签: swift

我有简单的二维数组,每行中元素的数量不同。我的目标是找到具有优雅解决方案的下一个元素。

如果有最后一个元素,我们应该得到第一个。

[
  [1, 0, 234, 345, 678],
  [123, 456, 789],
  [0, 9]
]

678 -> 123
9 -> 1

3 个答案:

答案 0 :(得分:1)

如果mat是一个嵌套数组,则mat.joined()是所有嵌套元素的“惰性平面集合”。这建议解决任意集合的问题:

  

给出一个集合和该集合的一个元素,返回该元素的直接后继。该集合被视为循环,因此最后一个元素的后继者是第一个元素。

直接实现是(内联说明):

extension Collection where Element: Comparable {
    func cyclicNext(after elem: Element) -> Element? {
        // Find (first) index of given element
        guard var idx = firstIndex(of: elem) else {
            return nil // Element not present in collection
        }
        formIndex(after: &idx) // Advance index by one
        if idx == endIndex { // If past the end ...
            idx = startIndex // ... then jump back to the start
        }
        return self[idx]
    }
}

如果元素在集合中出现多次,则返回第一次出现的后继者。

这可以应用于您的矩阵:

let mat: [[Int]] = [[1, 0, 234, 345, 678],
                    [123, 456, 789],
                    [0, 9]]

print(mat.joined().cyclicNext(after: 1))    // 0
print(mat.joined().cyclicNext(after: 678))  // 123
print(mat.joined().cyclicNext(after: 123))  // 456
print(mat.joined().cyclicNext(after: 9))    // 1
print(mat.joined().cyclicNext(after: 999))  // nil

它也可以应用于其他集合:

print([1, 3, 5, 7].cyclicNext(after: 3))    // 5
print([1, 3, 5, 7].cyclicNext(after: 7))    // 1

print("Hello World".cyclicNext(after: "W")) // "o"
print("Hello World".cyclicNext(after: "d")) // "H"

答案 1 :(得分:0)

一种可能的解决方案是将阵列弄平。

在操场上测试过:

let mat: [[Int]] = [[1, 0, 234, 345, 678],
                    [123, 456, 789],
                    [0, 9]]

func next(element: Int, in matrix: [[Int]]) -> Int? {
    let flatten = matrix.flatMap({ $0 })
    guard let index = flatten.firstIndex(of: element) else {
        print("Element \(element) not found in matrix")
        return nil
    }
    if index == flatten.endIndex - 1 {
        return flatten.first
    } else {
        return flatten[index + 1 ]
    }
}


let result1 = next(element: 678, in: mat)
print("End of subarray Test: \(result1)")
let result2 = next(element: 9, in: mat)
print("Last one Test: \(result2)")
let result3 = next(element: 66, in: mat)
print("Not present test: \(result3)")
let result0 = next(element: 1, in: mat)
print("First one test: \(result0)")

输出:

$>End of subarray Test: Optional(123)
$>Last one Test: Optional(1)
$>Element 66 not found in matrix
$>Not present test: nil
$>First one test: Optional(0)

我不知道它是否对您来说足够优雅。 一种优化将必须保留flatten,而不必每次都重新计算。

答案 2 :(得分:0)

我相信这确实可以做到:

extension Array where Element == [Int] {
    func element(after x: Int) -> Int? {
        var arrayIndex = 0
        while arrayIndex < self.count {
            //If an array contains the searched element
            if let xIndex = self[arrayIndex].firstIndex(where: { $0 == x }) {
                //if the next element is in the same array
                if xIndex < self[arrayIndex].count - 1 {
                    return self[arrayIndex][xIndex + 1]
                }
                //if the next element is in the next array
                else if arrayIndex < self.count - 1 {
                    return self[arrayIndex + 1][0]
                }
                //if the x is the last element in the last array
                else {
                    return self[0][0]
                }
            }
            arrayIndex += 1
        }
        return nil
    }
}

这是一些测试用例:

let mat = [
    [1, 0, 234, 345, 678],
    [123, 456, 789],
    [0, 9]
]
mat.element(after: 678) //123
mat.element(after: 9)   //1
mat.element(after: 1)   //0
mat.element(after: 0)   //234
mat.element(after: 3)   //nil