web-dev-qa-db-ja.com

どのようにforループを逆の順番で繰り返すのですか?

Playgroundでforループを使用すると、forループの最初のパラメータを最大値に変更するまで、すべてうまくいきました。 (降順に繰り返します)

これはバグですか?他に誰かがそれを持っていましたか?

for index in 510..509
{
    var a = 10
}

実行される反復回数を表示するカウンタは、刻々と過ぎます...

enter image description here

157
Krishnan

Xcode 6 Beta 4では、2つの関数が追加されました。1つ以外のステップで範囲を反復するためのものです。stride(from: to: by:)は排他範囲で、stride(from: through: by:)は包含範囲で使用されます。

範囲を逆の順序で繰り返すには、以下のように使用できます。

for index in stride(from: 5, to: 1, by: -1) {
    print(index)
}
//prints 5, 4, 3, 2

for index in stride(from: 5, through: 1, by: -1) {
    print(index)
}
//prints 5, 4, 3, 2, 1

どちらもRangeメンバー関数ではないことに注意してください。これらはStrideToまたはStrideThrough構造体を返すグローバル関数で、これらはRange構造体とは異なる方法で定義されています。

この回答の以前のバージョンでは、ベータ4では削除されたRange構造体のby()メンバー関数を使用しました。それがどのように機能するかを知りたい場合は、編集履歴を確認してください。

183
Cezar

範囲に逆関数を適用して逆方向に反復します。

Swift 1.2以前の場合:

// Print 10 through 1
for i in reverse(1...10) {
    println(i)
}

これは半開きの範囲でも動作します。

// Print 9 through 1
for i in reverse(1..<10) {
    println(i)
}

注:reverse(1...10)[Int]型の配列を作成するので、これは狭い範囲では問題ないかもしれませんが、以下に示すようにlazyを使用するか、範囲が大きい場合は受け入れられたstrideの回答を検討することをお勧めします。


大きな配列を作成しないようにするには、lazyreverse()を使用します。次のテストはPlaygroundで効率的に実行され、1兆のIntsの配列を作成していないことを示しています。

テスト:

var count = 0
for i in lazy(1...1_000_000_000_000).reverse() {
    if ++count > 5 {
        break
    }
    println(i)
}

Xcode 7のSwift 2.の場合:

for i in (1...10).reverse() {
    print(i)
}

Swift 2.0では、(1...1_000_000_000_000).reverse()ReverseRandomAccessCollection<(Range<Int>)>型なので、これはうまくいきます:

var count = 0
for i in (1...1_000_000_000_000).reverse() {
    count += 1
    if count > 5 {
        break
    }
    print(i)
}

Swift 3.reverse()reversed()に改名されました。

for i in (1...10).reversed() {
    print(i) // prints 10 through 1
}
200
vacawama

Swift 3用に更新されました

以下の答えは利用可能なオプションの要約です。あなたのニーズに最も合うものを選んでください。

reversed:範囲内の数値

進む

for index in 0..<5 {
    print(index)
}

// 0
// 1
// 2
// 3
// 4

後方

for index in (0..<5).reversed() {
    print(index)
}

// 4
// 3
// 2
// 1
// 0

reversedSequenceType内の要素

let animals = ["horse", "cow", "camel", "sheep", "goat"]

進む

for animal in animals {
    print(animal)
}

// horse
// cow
// camel
// sheep
// goat

後方

for animal in animals.reversed() {
    print(animal)
}

// goat
// sheep
// camel
// cow
// horse

reversed:インデックスを持つ要素

コレクションを反復処理するときにインデックスが必要になることがあります。そのためにはTupleを返すenumerate()を使うことができます。 Tupleの最初の要素はインデックスで、2番目の要素はオブジェクトです。

let animals = ["horse", "cow", "camel", "sheep", "goat"]

進む

for (index, animal) in animals.enumerated() {
    print("\(index), \(animal)")
}

// 0, horse
// 1, cow
// 2, camel
// 3, sheep
// 4, goat

後方

for (index, animal) in animals.enumerated().reversed()  {
    print("\(index), \(animal)")
}

// 4, goat
// 3, sheep
// 2, camel
// 1, cow
// 0, horse

Ben Lachmanが 彼の答え で述べたように、おそらく.enumerated().reversed()ではなく.reversed().enumerated()をしたいと思うでしょう(これはインデックス番号を増加させるでしょう)。

ストライド:数字

ストライドは、範囲を使用せずに反復する方法です。 2つの形式があります。コードの最後にあるコメントは、範囲バージョンがどうなるかを示しています(増分サイズが1であると仮定して)。

startIndex.stride(to: endIndex, by: incrementSize)      // startIndex..<endIndex
startIndex.stride(through: endIndex, by: incrementSize) // startIndex...endIndex

進む

for index in stride(from: 0, to: 5, by: 1) {
    print(index)
}

// 0
// 1
// 2
// 3
// 4

後方

増分サイズを-1に変更すると、後ろに戻ることができます。

for index in stride(from: 4, through: 0, by: -1) {
    print(index)
}

// 4
// 3
// 2
// 1
// 0

tothroughの違いに注意してください。

ストライド:SequenceTypeの要素

2ずつ進む

let animals = ["horse", "cow", "camel", "sheep", "goat"]

この例では、2を使って別の可能性を示します。

for index in stride(from: 0, to: 5, by: 2) {
    print("\(index), \(animals[index])")
}

// 0, horse
// 2, camel
// 4, goat

後方

for index in stride(from: 4, through: 0, by: -1) {
    print("\(index), \(animals[index])")
}

// 4, goat
// 3, sheep 
// 2, camel
// 1, cow  
// 0, horse 

ノート

83
Suragch

Swift 4以降

for i in stride(from: 5, to: 0, by: -1) {
    print(i)
}
//prints 5, 4, 3, 2, 1

for i in stride(from: 5, through: 0, by: -1) {
    print(i)
}
//prints 5, 4, 3, 2, 1, 0
48
Irfan

Swift 2.0以降では、範囲コレクションに逆方向に適用する必要があります。

for i in (0 ..< 10).reverse() {
  // process
}

Swift 3.0では、名前が.reversed()に変更されました。

27
Andrew Luca

Swift 5では、必要に応じて、問題を解決するために、次の4つのPlaygroundコード例のいずれかを選択できます。


#1 ClosedRangereversed()メソッドの使用

ClosedRangename__には、 reversed() というメソッドがあります。 reversed()メソッドは以下の宣言をしています。

func reversed() -> ReversedCollection<ClosedRange<Bound>>

コレクションの要素を逆の順序で表示するビューを返します。

使用法:

let reversedCollection = (0 ... 5).reversed()

for index in reversedCollection {
    print(index)
}

/*
Prints:
5
4
3
2
1
0
*/

代わりに、Rangereversed() methodを使用することもできます。

let reversedCollection = (0 ..< 6).reversed()

for index in reversedCollection {
    print(index)
}

/*
Prints:
5
4
3
2
1
0
*/

#2 sequence(first:next:)関数を使う

Swift標準ライブラリには、 sequence(first:next:) という関数があります。 sequence(first:next:)の宣言は以下のとおりです。

func sequence<T>(first: T, next: @escaping (T) -> T?) -> UnfoldFirstSequence<T>

firstname__と、nextname__を繰り返し遅延適用して形成されたシーケンスを返します。

使用法:

let unfoldSequence = sequence(first: 5, next: {
    $0 > 0 ? $0 - 1 : nil
})

for index in unfoldSequence {
    print(index)
}

/*
Prints:
5
4
3
2
1
0
*/

#3。 stride(from:through:by:)関数を使う

Swift標準ライブラリには、 stride(from:through:by:) という関数があります。 stride(from:through:by:)の宣言は以下のとおりです。

func stride<T>(from start: T, through end: T, by stride: T.Stride) -> StrideThrough<T> where T : Strideable

開始値から終了値に向かって、場合によっては終了値までのシーケンスを、指定された量ずつステップして返します。

使用法:

let sequence = stride(from: 5, through: 0, by: -1)

for index in sequence {
    print(index)
}

/*
Prints:
5
4
3
2
1
0
*/

代わりに、 stride(from:to:by:) を使うこともできます。

let sequence = stride(from: 5, to: -1, by: -1)

for index in sequence {
    print(index)
}

/*
Prints:
5
4
3
2
1
0
*/

#4。 AnyIteratorinit(_:)イニシャライザの使用

AnyIteratorname__には、 init(_:) という初期化子があります。 init(_:)の宣言は以下のとおりです。

init(_ body: @escaping () -> AnyIterator<Element>.Element?)

指定されたクロージャをnext()メソッドでラップするイテレータを作成します。

使用法:

var index = 5

guard index >= 0 else { fatalError("index must be positive or equal to zero") }

let iterator = AnyIterator({ () -> Int? in
    defer { index = index - 1 }
    return index >= 0 ? index : nil
})

for index in iterator {
    print(index)
}

/*
Prints:
5
4
3
2
1
0
*/

必要に応じて、Intname__の拡張メソッドを作成し、その中にイテレータをラップすることで、前のコードをリファクタリングできます。

extension Int {

    func iterateDownTo(_ endIndex: Int) -> AnyIterator<Int> {
        var index = self
        guard index >= endIndex else { fatalError("self must be greater than or equal to endIndex") }

        let iterator = AnyIterator { () -> Int? in
            defer { index = index - 1 }
            return index >= endIndex ? index : nil
        }
        return iterator
    }

}

let iterator = 5.iterateDownTo(0)

for index in iterator {
    print(index)
}

/*
Prints:
5
4
3
2
1
0
*/
20
Imanou Petit

Swift 4以降

    let count = 50//For example
    for i in (1...count).reversed() {
        print(i)
    }
7
Rohit Sisodia

Swift 4.

for i in stride(from: 5, to: 0, by: -1) {
    print(i) // 5,4,3,2,1
}

to値を含める場合は、次のようにします。

for i in stride(from: 5, through: 0, by: -1) {
    print(i) // 5,4,3,2,1,0
}
4
William Hu

逆の場合に配列Arrayまたはより一般的には任意のSequenceType)を反復したい場合。いくつか追加のオプションがあります。

まず、配列をreverse()して通常通りループすることができます。しかし、オブジェクトとインデックスを含むタプルを出力するので、私はenumerate()を使うことを好みます。

ここで注意すべきことは、正しい順番でこれらを呼び出すことが重要であるということです。

for (index, element) in array.enumerate().reverse()

降順でインデックスを生成します(これが私の一般的な予想です)。一方:

for (index, element) in array.reverse().enumerate()(これはNSArrayのreverseEnumeratorに近いものです)

配列を逆方向に移動しますが、昇順のインデックスを出力します。

3
Ben Lachman

Swift 2.2、Xcode 7.3(10、2016年6月):

for (index,number) in (0...10).enumerate() {
    print("index \(index) , number \(number)")
}

for (index,number) in (0...10).reverse().enumerate() {
    print("index \(index) , number \(number)")
}

出力:

index 0 , number 0
index 1 , number 1
index 2 , number 2
index 3 , number 3
index 4 , number 4
index 5 , number 5
index 6 , number 6
index 7 , number 7
index 8 , number 8
index 9 , number 9
index 10 , number 10


index 0 , number 10
index 1 , number 9
index 2 , number 8
index 3 , number 7
index 4 , number 6
index 5 , number 5
index 6 , number 4
index 7 , number 3
index 8 , number 2
index 9 , number 1
index 10 , number 0
2
PeiweiChen

代わりにCスタイルのwhileループを使用することを検討できます。これはSwift 3では問題なく動作します。

var i = 5 
while i > 0 { 
    print(i)
    i -= 1
}
1
Nitin Nain

値を簡単に元に戻すには、reverse()メソッドを使用できます。

var i:Int
for i in 1..10.reversed() {
    print(i)
}

Reverse()メソッドは値を逆にします。

1
SIDHARTH P U
var sum1 = 0
for i in 0...100{
    sum1 += i
}
print (sum1)

for i in (10...100).reverse(){
    sum1 /= i
}
print(sum1)
1
Abo3atef

このために、非常に簡単なwhileループを使用できます。

var i = 10
while i > 1{
   print(i)
   i = i - 1
}

ただし、forループを使用する場合は、reversed()メソッドを使用します

for i in (1...10).reversed(){
    print(i)
}
0
Abhishek Sharma