在序列数组中分离奇数和偶数索引

Pet*_*994 8 arrays swift

for循环中的for不起作用,因为int类型不符合协议序列.

我有3个数组:

1个主数组,存储数组

1个奇数阵,开头为空

1个偶数组,开头为空

意思是主阵列的所有奇数索引将存储在奇数阵列中,而偶数阵列则相同.

    while i < masterA.count {
        evenA.append(masterA[i])
        if i > 0{
        oddA.append(masterA[i - 1])
        }
        i += 2
    }
Run Code Online (Sandbox Code Playgroud)

然而,这不够好.谁有更好的主意?

Mar*_*n R 17

这是另一种可能的解决方案

let evenA = stride(from: 0, to: masterA.count, by: 2).map { masterA[$0] }
let oddA = stride(from: 1, to: masterA.count, by: 2).map { masterA[$0] }
Run Code Online (Sandbox Code Playgroud)

元素直接从源阵列中的偶数/奇数位置"拾取".

表现比较:

我简单而不是非常复杂的特殊基准测试代码:

import Swift

let N = 10_000_000
let RUNS = 50

let masterA = (0..<N).map { $0 }

var times = (0.0, 0.0, 0.0, 0.0)
for _ in 1...RUNS {

    // filter+map (dfri)
    do {
        let start = Date()
        let evenA = masterA.enumerated().filter { $0.0 % 2 == 0 }.map{ $0.1 }
        let oddA = masterA.enumerated().filter { $0.0 % 2 != 0 }.map{ $0.1 }
        let time = Date().timeIntervalSince(start)
        times.0 += time
    }

    // flatMap (dfri)
    do {
        let start = Date()
        let evenA = masterA.enumerated().flatMap { $0 % 2 == 0 ? $1 : nil }
        let oddA = masterA.enumerated().flatMap { $0 % 2 != 0 ? $1 : nil }
        let time = Date().timeIntervalSince(start)
        times.1 += time
    }

    // stride+map (me)
    do {
        let start = Date()
        let evenA = stride(from: 0, to: masterA.count, by: 2).map { masterA[$0] }
        let oddA = stride(from: 1, to: masterA.count, by: 2).map { masterA[$0] }
        let time = Date().timeIntervalSince(start)
        times.2 += time
    }

    // loop (Keiwan)
    do {
        let start = Date()
        var evenA = [Int]()
        var oddA = [Int]()

        for (index, element) in masterA.enumerated() {
            if index % 2 == 0 {
                evenA.append(element)
            } else {
                oddA.append(element)
            }
        }
        let time = Date().timeIntervalSince(start)
        times.3 += time
    }
}

print(N, RUNS)
print(times.0/Double(RUNS), times.1/Double(RUNS), times.2/Double(RUNS), times.3/Double(RUNS))
Run Code Online (Sandbox Code Playgroud)

结果:(在MacBook上,在发布模式下运行)

#elements   filter+map  flatMap   stride+map  loop
10,000      0.0001      0.00008   0.00004     0.00004
100,000     0.0016      0.0008    0.0004      0.0004
1,000,000   0.0295      0.0136    0.0090      0.0091
10,000,000  0.3025      0.1332    0.0909      0.1250


Kei*_*wan 6

您可以使用enumerated()在循环时获取索引和值:

for (index, element) in masterA.enumerated() {
    if index % 2 == 0 {
        evenA.append(element)
    } else {
        oddA.append(element)
    }
}
Run Code Online (Sandbox Code Playgroud)

这将每个存储elementmasterA与奇数指数oddA和每一个元素与索引为偶数evenA.

  • @RajanMaheshwari:`0`是一个偶数,所以在`evenA`中存储索引为'0`的元素对我来说似乎是正确的. (3认同)
  • @RajanMaheshwari另外,OP特别要求奇_indices_(_"......主数组的所有**奇数索引**将存储在**奇数数组**..."_),这可能暗示OP对奇数/偶数顺序的观点与此答案相同. (3认同)

dfr*_*fri 5

也许我误解你的意图,但它好像你想要的元素masterA具有奇数索引应存放在oddA,相反,元素masterA有偶数索引应存放在evenA.

你可以通过过滤随时可用masterA的指数来实现这一目标.masterAmasterA.enumerated()

let masterA = [4, 5, 2, 1, 7, 8, 1]

let evenA = masterA.enumerated().filter { $0.0 % 2 == 0 }.map{ $0.1 }
let oddA = masterA.enumerated().filter { $0.0 % 2 != 0 }.map{ $0.1 }

print(evenA) // [4, 2, 7, 1]
print(oddA)  // [5, 1, 8]
Run Code Online (Sandbox Code Playgroud)

正如@Hamish在下面的评论中指出的那样,我们可以使用compactMap(Swift 3 :)flatMap替代链式filtermap.

let evenA = masterA.enumerated().compactMap { $0 % 2 == 0 ? $1 : nil }
let oddA = masterA.enumerated().compactMap { $0 % 2 != 0 ? $1 : nil }
Run Code Online (Sandbox Code Playgroud)

后一种compactMap解决方案更简洁,而filter...... map解决方案可能显示出更清晰的意图.在这个特殊的简洁与语义竞争中,我个人更喜欢这个compactMap解决方案.

  • 当然,`filter`和`map`总是可以归结为`flatMap` - `let evenA = masterA.enumerated().flatMap {$ 0%2 == 0?$ 1:无}`:) (2认同)