在矩阵中查找下一个元素

问题描述 投票:-1回答:3

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

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

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

678 -> 123
9 -> 1
swift
3个回答
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"

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

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而不是每次都重新计算。

© www.soinside.com 2019 - 2024. All rights reserved.