ios 如何快速以相反的顺序迭代for循环?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/24508592/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-31 01:11:57  来源:igfitidea点击:

How to iterate for loop in reverse order in swift?

iosswiftswift-playground

提问by Krishnan

When I use the for loop in Playground, everything worked fine, until I changed the first parameter of for loop to be the highest value. (iterated in descending order)

当我在 Playground 中使用 for 循环时,一切正常,直到我将 for 循环的第一个参数更改为最高值。(按降序迭代)

Is this a bug? Did any one else have it?

这是一个错误吗?其他人有吗?

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

The counter that displays the number of iterations that will be executions keeps ticking...

显示将要执行的迭代次数的计数器一直在滴答作响......

enter image description here

在此处输入图片说明

回答by Cezar

Xcode 6 beta 4 added two functions to iterate on ranges with a step other than one: stride(from: to: by:), which is used with exclusive ranges and stride(from: through: by:), which is used with inclusive ranges.

Xcode 6 beta 4 添加了两个函数来迭代范围stride(from: to: by:),而不是一个步骤: ,用于独占范围和stride(from: through: by:),用于包含范围。

To iterate on a range in reverse order, they can be used as below:

要以相反的顺序迭代范围,它们可以如下使用:

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

Note that neither of those is a Rangemember function. They are global functions that return either a StrideToor a StrideThroughstruct, which are defined differently from the Rangestruct.

请注意,这些都不是Range成员函数。它们是返回 aStrideToStrideThrough结构体的全局函数,它们的定义与Range结构体不同。

A previous version of this answer used the by()member function of the Rangestruct, which was removed in beta 4. If you want to see how that worked, check the edit history.

此答案的先前版本使用了结构的by()成员函数,该成员函数Range已在 beta 4 中删除。如果您想了解它是如何工作的,请检查编辑历史记录。

回答by vacawama

Apply the reverse function to the range to iterate backwards:

将 reverse 函数应用于范围以向后迭代:

For Swift 1.2and earlier:

对于Swift 1.2及更早版本:

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

It also works with half-open ranges:

它也适用于半开范围:

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

Note: reverse(1...10)creates an array of type [Int], so while this might be fine for small ranges, it would be wise to use lazyas shown below or consider the accepted strideanswer if your range is large.

注意: reverse(1...10)创建一个 type 数组[Int],因此虽然这对于小范围可能没问题,但最好lazy按如下所示使用,或者stride如果您的范围很大,请考虑接受的答案。



To avoid creating a large array, use lazyalong with reverse(). The following test runs efficiently in a Playground showing it is not creating an array with one trillion Ints!

为避免创建大型数组,请lazy与 一起使用reverse()。以下测试在 Playground 中有效运行,表明它没有创建一个具有 1 万亿Ints的数组!

Test:

测试:

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


For Swift 2.0in Xcode 7:

对于Xcode 7 中的Swift 2.0

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

Note that in Swift 2.0, (1...1_000_000_000_000).reverse()is of type ReverseRandomAccessCollection<(Range<Int>)>, so this works fine:

请注意,在 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)
}


For Swift 3.0reverse()has been renamed to reversed():

对于Swift 3.0reverse()已重命名为reversed()

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

回答by Suragch

Updated for Swift 3

为 Swift 3 更新

The answer below is a summary of the available options. Choose the one that best fits your needs.

下面的答案是可用选项的摘要。选择最适合您需求的一种。

reversed: numbers in a range

reversed: 范围内的数字

Forward

向前

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

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

Backward

落后

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

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

reversed: elements in SequenceType

reversed: 中的元素 SequenceType

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

Forward

向前

for animal in animals {
    print(animal)
}

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

Backward

落后

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

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

reversed: elements with an index

reversed: 带有索引的元素

Sometimes an index is needed when iterating through a collection. For that you can use enumerate(), which returns a tuple. The first element of the tuple is the index and the second element is the object.

有时在遍历集合时需要索引。为此,您可以使用enumerate(),它返回一个元组。元组的第一个元素是索引,第二个元素是对象。

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

Forward

向前

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

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

Backward

落后

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

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

Note that as Ben Lachman noted in his answer, you probably want to do .enumerated().reversed()rather than .reversed().enumerated()(which would make the index numbers increase).

请注意,正如 Ben Lachman 在他的回答中指出的那样,您可能想要做.enumerated().reversed()而不是.reversed().enumerated()(这会使索引数增加)。

stride: numbers

步幅:数字

Stride is way to iterate without using a range. There are two forms. The comments at the end of the code show what the range version would be (assuming the increment size is 1).

Stride 是一种不使用范围进行迭代的方法。有两种形式。代码末尾的注释显示了范围版本(假设增量大小为 1)。

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

Forward

向前

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

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

Backward

落后

Changing the increment size to -1allows you to go backward.

更改增量大小以-1允许您后退。

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

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

Note the toand throughdifference.

注意tothrough区别。

stride: elements of SequenceType

步幅:SequenceType 的元素

Forward by increments of 2

以 2 为增量前进

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

I'm using 2in this example just to show another possibility.

2在这个例子中使用只是为了展示另一种可能性。

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

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

Backward

落后

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

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

Notes

笔记

回答by Irfan

Swift 4onwards

斯威夫特 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

回答by Andrew Luca

For Swift 2.0 and above you should apply reverse on a range collection

对于 Swift 2.0 及更高版本,您应该在范围集合上应用 reverse

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

It has been renamed to .reversed() in Swift 3.0

它已在 Swift 3.0 中重命名为 .reversed()

回答by Imanou Petit

With Swift 5, according to your needs, you may choose one of the four following Playground code examplesin order to solve your problem.

使用 Swift 5,您可以根据需要,选择以下四个 Playground 代码示例之一来解决您的问题。



#1. Using ClosedRangereversed()method

#1. 使用ClosedRangereversed()方法

ClosedRangehas a method called reversed(). reversed()method has the following declaration:

ClosedRange有一个方法叫做reversed(). reversed()方法具有以下声明:

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

Returns a view presenting the elements of the collection in reverse order.

返回一个以相反顺序呈现集合元素的视图。

Usage:

用法:

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

for index in reversedCollection {
    print(index)
}

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

As an alternative, you can use Rangereversed()method:

作为替代方案,您可以使用Rangereversed()方法:

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

for index in reversedCollection {
    print(index)
}

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


#2. Using sequence(first:next:)function

#2. 使用sequence(first:next:)功能

Swift Standard Library provides a function called sequence(first:next:). sequence(first:next:)has the following declaration:

Swift 标准库提供了一个名为sequence(first:next:). sequence(first:next:)有以下声明:

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

Returns a sequence formed from firstand repeated lazy applications of next.

返回由 的first重复惰性应用形成的序列next

Usage:

用法:

let unfoldSequence = sequence(first: 5, next: {
    
func stride<T>(from start: T, through end: T, by stride: T.Stride) -> StrideThrough<T> where T : Strideable
> 0 ?
let sequence = stride(from: 5, through: 0, by: -1)

for index in sequence {
    print(index)
}

/*
Prints:
5
4
3
2
1
0
*/
- 1 : nil }) for index in unfoldSequence { print(index) } /* Prints: 5 4 3 2 1 0 */


#3. Using stride(from:through:by:)function

#3. 使用stride(from:through:by:)功能

Swift Standard Library provides a function called stride(from:through:by:). stride(from:through:by:)has the following declaration:

Swift 标准库提供了一个名为stride(from:through:by:). stride(from:through:by:)有以下声明:

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

for index in sequence {
    print(index)
}

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

Returns a sequence from a starting value toward, and possibly including, an end value, stepping by the specified amount.

返回从起始值到(可能包括)结束值的序列,按指定量步进。

Usage:

用法:

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

As an alternative, you can use stride(from:to:by:):

作为替代方案,您可以使用stride(from:to:by:)

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
*/


#4. Using AnyIteratorinit(_:)initializer

#4. 使用AnyIteratorinit(_:)初始化程序

AnyIteratorhas an initializer called init(_:). init(_:)has the following declaration:

AnyIterator有一个名为init(_:). init(_:)有以下声明:

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
*/

Creates an iterator that wraps the given closure in its next()method.

创建一个迭代器,将给定的闭包包装在其next()方法中。

Usage:

用法:

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

If needed, you can refactor the previous code by creating an extension method for Intand wrapping your iterator in it:

如果需要,您可以通过为其创建扩展方法Int并将迭代器包装在其中来重构之前的代码:

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

回答by Rohit Sisodia

In Swift 4 and latter

在 Swift 4 及更高版本中

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

回答by William Hu

Swift 4.0

斯威夫特 4.0

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

If you want to include the tovalue:

如果要包含该to值:

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

回答by Ben Lachman

If one is wanting to iterate through an array(Arrayor more generally any SequenceType) in reverse. You have a few additional options.

如果想要反向迭代一个数组Array或更一般的 any SequenceType)。您还有一些额外的选择。

First you can reverse()the array and loop through it as normal. However I prefer to use enumerate()much of the time since it outputs a tuple containing the object and it's index.

首先,您可以reverse()正常访问数组并循环遍历它。但是我更喜欢使用enumerate()大部分时间,因为它输出一个包含对象及其索引的元组。

The one thing to note here is that it is important to call these in the right order:

这里要注意的一件事是,以正确的顺序调用这些很重要:

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

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

yields indexes in descending order (which is what I generally expect). whereas:

按降序生成索引(这是我通常期望的)。然而:

for (index, element) in array.reverse().enumerate()(which is a closer match to NSArray's reverseEnumerator)

for (index, element) in array.reverse().enumerate()(这更接近于 NSArray 的reverseEnumerator

walks the array backward but outputs ascending indexes.

向后遍历数组但输出升序索引。

回答by PeiweiChen

as for Swift 2.2 , Xcode 7.3 (10,June,2016) :

至于 Swift 2.2 , Xcode 7.3 (10,June,2016) :

##代码##

Output :

输出 :

##代码##