简体   繁体   English

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

[英]Separate odd and even indexes in a sequence array

A for in loop won't work because type int is does not conform to protocol Sequence. for循环中的for不起作用,因为int类型不符合协议序列。

I have 3 arrays: 我有3个数组:

1 master array, where the array is stored 1个主数组,存储数组

1 odd array, empty at the beginning 1个奇数阵,开头为空

1 even array, empty at the beginning 1个偶数组,开头为空

The meaning is that all the odd indexes of the master array will be stored at the odd array, and the same for the even array. 意思是主阵列的所有奇数索引将存储在奇数阵列中,而偶数阵列则相同。

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

However this does not work good enough. 然而,这不够好。 Anyone has a better idea? 谁有更好的主意?

Here is another possible solution: 这是另一种可能的解决方案

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] }

The elements are "picked" directly from the even/odd positions in the source array. 元素直接从源阵列中的偶数/奇数位置“拾取”。

Performance comparison: 表现比较:

My simple, not very sophisticated ad-hoc benchmarking code: 我简单而不是非常复杂的特殊基准测试代码:

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

Results: (On a MacBook, running in Release mode) 结果:(在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

You can use enumerated() to get both the index and the value while looping: 在循环时,您可以使用enumerated()来获取索引和值:

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

This will store every element of masterA with an odd index in oddA and every element with an even index in evenA . 这将存储masterA每个element ,其中奇数索引在oddA ,每个元素在evenA具有偶数索引。

Possibly I'm misunderstanding your intent, but it seems as if you want that elements of masterA that have odd indices should be stored in oddA , and conversely, elements of masterA that have even indices should be stored in evenA . 可能我误解了你的意图,但似乎你想要将具有奇数索引的masterA 元素存储在oddA ,相反,具有偶数索引的masterA元素应该存储在evenA

You can achieve this by filtering masterA wrt the indices of masterA , readily available from masterA.enumerated() . 您可以通过过滤实现这一masterA WRT的指数masterA ,随时可从masterA.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]

As @Hamish points out in his comment below, we could use the compactMap (Swift 3: flatMap ) as an alternative to the chained filter and map . 正如@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 }

The latter compactMap solution is briefer, whereas the filter ... map solution possibly shows intent slightly clearer. 后一个compactMap解决方案更简洁,而filter ... map解决方案可能显示意图稍微清晰。 In this particular brevity vs. semantics competition, I would personally prefer the compactMap solution. 在这个特殊的简洁与语义竞争中,我个人更喜欢compactMap解决方案。

Another solution 另一种方法

Swift 3.0 code Swift 3.0代码

let array = [1,2,3,4,5,6,7,8]
var oddArray = [Int]()
var evenArray = [Int]()

for (index,value) in array.enumerated() {
    if index % 2 == 0 {
        // It is odd because index starts from 0 in array and I am assuming the 0 index as the odd one.
        oddArray.append(value)
    } else {
        evenArray.append(value)
    }
}

Odd Array = [1,3,5,7] 奇数阵= [1,3,5,7]
Even Array = [2,4,6,8] 甚至数组= [2,4,6,8]

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM