swift 如何调用嵌套循环一次一个循环?

rbpvctlc  于 2022-12-26  发布在  Swift
关注(0)|答案(1)|浏览(203)

我想把每个元素和其他元素进行比较,比如abc变量的数量是动态的,但是每个变量的数组大小是统一的。

let a = [1, 2, 3]
let b = [3, 4, 5]
let c = [4, 5, 6]

for i in a {
    for j in b {
        for k in c {
            /// comparison
        }
    }
}

与其一次从开始到结束循环,不如用什么方法在调用时进行每次比较?例如:

compare(iteration: 0)
/// compares a[0], b[0], c[0]

compare(iteration: 1)
/// compares a[0], b[0], c[1]

/// all the way to
/// compares a[2], b[2], c[2]

或者,它甚至可以像下面这样:

next()
/// compares a[0], b[0], c[0]

next()
/// compares a[0], b[0], c[1]

几乎就像一个迭代器遍历调用所指定的每个循环一样。

oaxa6hgo

oaxa6hgo1#

令数组的个数为n,并令每个数组中的元素个数为k,这保证了所有数组都是相同的。
然后创建一个由整数0到k-1组成的数组,重复n次。例如,在您的示例中,n为3,k为3,因此生成该数组

[0, 1, 2, 0, 1, 2, 0, 1, 2]

现在获取该数组的n元素的所有 * 组合 *。您可以使用https://github.com/apple/swift-algorithms/blob/main/Guides/Combinations.md中的算法来完成此操作。唯一化结果(例如,通过强制为Set,然后再返回Array)。这将以某种顺序提供等效于

[[0, 1, 2], [0, 1, 0], [0, 1, 1], [0, 2, 0], [0, 2, 1], [0, 2, 2], [0, 0, 1], [0, 0, 2], [0, 0, 0], [1, 2, 0], [1, 2, 1], [1, 2, 2], [1, 0, 1], [1, 0, 2], [1, 0, 0], [1, 1, 2], [1, 1, 0], [1, 1, 1], [2, 0, 1], [2, 0, 2], [2, 0, 0], [2, 1, 2], [2, 1, 0], [2, 1, 1], [2, 2, 0], [2, 2, 1], [2, 2, 2]]

你可以很容易地看到,这些都是数字0、1和2的27种可能组合,但这正是你在for循环中所做的!所以现在,使用这些子数组分别作为每个原始数组的索引。
例如,使用我的结果和你原来的例子,第一个子数组[0, 1, 2]得到[1, 4, 6]--第一个值来自第一个数组,第二个值来自第二个数组,第三个值来自第三个数组,依此类推。
这样,通过从每个原始数组中选择一个值,您将生成所有可能的n元组,这就是所需的结果;而且我们也不受nk的固定值的约束,这是您想要实现的,然后您将能够“比较”每个n元组的元素,无论这对您来说意味着什么(您在问题中没有说明它的含义)。
在原始值的情况下,我们将得到这些n元组(表示为数组):

[1, 4, 6]
[1, 4, 4]
[1, 4, 5]
[1, 5, 4]
[1, 5, 5]
[1, 5, 6]
[1, 3, 5]
[1, 3, 6]
[1, 3, 4]
[2, 5, 4]
[2, 5, 5]
[2, 5, 6]
[2, 3, 5]
[2, 3, 6]
[2, 3, 4]
[2, 4, 6]
[2, 4, 4]
[2, 4, 5]
[3, 3, 5]
[3, 3, 6]
[3, 3, 4]
[3, 4, 6]
[3, 4, 4]
[3, 4, 5]
[3, 5, 4]
[3, 5, 5]
[3, 5, 6]

这些正是你所追求的三重价值观。
实际代码:

// your original conditions
    let a = [1, 2, 3]
    let b = [3, 4, 5]
    let c = [4, 5, 6]

    let originals = [a, b, c]

    // The actual solution starts here. Note that I never use any hard
    // coded numbers.
    let n = originals.count
    let k = originals[0].count
    var indices = [Int]()
    for _ in 0..<n {
        for i in 0..<k {
            indices.append(i)
        }
    }
    let combos = Array(indices.combinations(ofCount: n))
    var combosUniq = [[Int]]()
    var combosSet = Set<[Int]>()
    for combo in combos {
        let success = combosSet.insert(combo)
        if success.inserted {
            combosUniq.append(combo)
        }
    }

    // And here's how to generate your actual desired values.
    for combo in combosUniq {
        var tuple = [Int]()
        for (outerIndex, innerIndex) in combo.enumerated() {
            tuple.append(originals[outerIndex][innerIndex])
        }
        print(tuple) // in real life, do something useful here
    }
}

相关问题