いろいろなforループ

Swift の for ループは、C言語のようにバラエティに富んだ書き方ができません。C言語で記述していたライブラリなどを Swift に翻訳する場合は、サラッと書き直せないので苦労がともないます。

たとえば高速フーリエ変換のC言語のコードでは下記のように動的に増分値が変化する書き方をしている場合が多いので Swift に移植するときに困りますね。

// これはC言語のコード.
for ( int n = 1; n < data; n *= 2 ) {
    printf( "%d\n", n );
}

とはいえ、なんとかうまくやる作戦がありますので、下記に列挙します。

普通にひとつづつ増やすループ

これは特に説明することはないです。普通のコードです。

// for ( int n = 0; n < NUM_LOOP; n++ ) {
//     printf( "%d\n", n );
// }

let NUM_LOOP = 16
for n in 0 ..< NUM_LOOP {
     print( n )
}

ひとつづつ逆ループ

reversed() を指定することで n が減っていきます。

// for ( int n = NUM_LOOP - 1; n >= 0; n-- ) {
//     printf( "%d\n", n );
// }

let NUM_LOOP = 16
for n in ( 0 ..< NUM_LOOP ).reversed() {
    print( n )
}

初期値、終了値、任意の増分で順ループ

初期値と終了値をきめて、インデックスの増分を指定します。
下記の例では n = n + 7 になります。
by: 1 とすれば 0 ..< NUM_LOOP と同じ動作になります。

// for ( int n = 0; n < NUM_LOOP; n += 7 ) {
//     printf( "%d\n", n );
// }

let NUM_LOOP = 16
for n in stride( from: 0, to: NUM_LOOP, by: 7 ) {
    print( n )
}

初期値、終了値、任意の増分で逆ループ

reversed() をつけることで逆の動きになります。

let NUM_LOOP = 16
for n in stride( from: 0, to: NUM_LOOP, by: 7 ).reversed() {
    print( n )
}

sequence を使ってループ (ループ変数に追加加算 )

めんどくさくなってきましたが、sequence を使うとループ変数にひと手間くわえることができます。ここの 2 という値は stride の場合の増分値は定数しか指定できませんでしたが、sequence の場合は変数も使えます。

// for ( int n = 0; n < NUM_LOOP; n += 2 ) {
//     printf( "%d\n", n );
// }

let NUM_LOOP = 16
for n in sequence( first: 0, next: { $0 + 2 }).prefix( while: { $0 < NUM_LOOP }) {
    print( n )
}

sequence を使って逆ループ (ループ変数に追加加算 )

これも reversed() を使うことで逆の動きになります。

let NUM_LOOP = 16
for n in sequence( first: 0, next: { $0 + 2 }).prefix( while: { $0 < NUM_LOOP }).reversed() {
    print( n )
}

sequence を使ってループ (ループ変数に追加乗算 )

sequence を使うとループ変数に追加乗算できたりしますが、初期値を0にすると、何をかけても0なので無限ループにならないように注意です。

// for ( int n = 1; n < NUM_LOOP; n *= 2 ) {
//     printf( "%d", n );
// }

let NUM_LOOP = 16
for n in sequence( first: 1, next: { $0 * 2 }).prefix( while: { $0 < NUM_LOOP }) {
    print( n )
}

sequence を使って逆ループ (ループ変数に追加乗算 )

もちろん reversed() で逆の動きになります。

let NUM_LOOP = 16
for n in sequence( first: 1, next: { $0 * 2 }).prefix( while: { $0 < NUM_LOOP }).reversed() {
    print( n )
}

実機で確認できるコード

下記が実機で動きを確認できるコードです。

XCode のコンソール出力に実行結果が print されますので、画面になにか結果があらわれるというわけではありませんのでご注意ください。

import SwiftUI

struct ContentView: View {

    let NUM_LOOP = 32

//    let STR_SEPARATE = "\r"
    let STR_SEPARATE = "--------"
    let COLOR_FG = Color.white
    let COLOR_BG = Color.blue

    var body: some View {

        VStack {

            // 普通にひとつづつ増やすループ.
            Button( action: {
                for n in 0 ..< NUM_LOOP {
                    print( n )
                }
                print( STR_SEPARATE )
            }){
                Text( "inc" )
                    .foregroundColor( COLOR_FG )
            }
            .padding()
            .background( COLOR_BG )

            // ひとつづつ逆ループ.
            Button( action: {
                for n in ( 0 ..< NUM_LOOP ).reversed() {
                    print( n )
                }
                print( STR_SEPARATE )
            }){
                Text( "rev" )
                    .foregroundColor( COLOR_FG )
            }
            .padding()
            .background( COLOR_BG )

            // 初期値、終了値、任意の増分で順ループ.
            Button( action: {
                for n in stride( from: 0, to: NUM_LOOP, by: 7 ) {
                    print( n )
                }
                print( STR_SEPARATE )
            }){
                Text( "stride" )
                    .foregroundColor( COLOR_FG )
            }
            .padding()
            .background( COLOR_BG )

            // 初期値、終了値、任意の増分で逆ループ.
            Button( action: {
                for n in stride( from: 0, to: NUM_LOOP, by: 7 ).reversed() {
                    print( n )
                }
                print( STR_SEPARATE )
            }){
                Text( "stride rev" )
                    .foregroundColor( COLOR_FG )
            }
            .padding()
            .background( COLOR_BG )

            // sequence を使ってループ.
            Button( action: {
                for n in sequence( first: 0, next: { $0 + 2 }).prefix( while: { $0 < NUM_LOOP })
                {
                    print( n )
                }
                print( STR_SEPARATE )
            }){
                Text( "seq ( n = n + 2 )" )
                    .foregroundColor( COLOR_FG )
            }
            .padding()
            .background( COLOR_BG )

            // sequence を使って逆ループ.
            Button( action: {
                for n in sequence( first: 0, next: { $0 + 2 }).prefix( while: { $0 < NUM_LOOP }).reversed()
                {
                    print( n )
                }
                print( STR_SEPARATE )
            }){
                Text( "seq ( n = n + 2 ) rev" )
                    .foregroundColor( COLOR_FG )
            }
            .padding()
            .background( COLOR_BG )

            // sequence を使ってループ.
            Button( action: {
                // first の値を 0 にすると、いつまでも終了値まで到達しないので無限ループになる.
                for n in sequence( first: 1, next: { $0 * 2 }).prefix( while: { $0 < NUM_LOOP })
                {
                    print( n )
                }
                print( STR_SEPARATE )
            }){
                Text( "seq ( n = n * 2 )" )
                    .foregroundColor( COLOR_FG )
            }
            .padding()
            .background( COLOR_BG )

            // sequence を使って逆ループ.
            Button( action: {
                // first の値を 0 にすると、いつまでも終了値まで到達しないので無限ループになる.
                for n in sequence( first: 1, next: { $0 * 2 }).prefix( while: { $0 < NUM_LOOP }).reversed()
                {
                    print( n )
                }
                print( STR_SEPARATE )
            }){
                Text( "seq ( n = n * 2 ) rev" )
                    .foregroundColor( COLOR_FG )
            }
            .padding()
            .background( COLOR_BG )

        }

    }

}

struct ContentView_Previews: PreviewProvider {
    static var previews: some View {
        ContentView()
    }
}