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
How to iterate for loop in reverse order in swift?
提问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...
显示将要执行的迭代次数的计数器一直在滴答作响......
回答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 Range
member function. They are global functions that return either a StrideTo
or a StrideThrough
struct, which are defined differently from the Range
struct.
请注意,这些都不是Range
成员函数。它们是返回 aStrideTo
或StrideThrough
结构体的全局函数,它们的定义与Range
结构体不同。
A previous version of this answer used the by()
member function of the Range
struct, 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 lazy
as shown below or consider the accepted stride
answer if your range is large.
注意: reverse(1...10)
创建一个 type 数组[Int]
,因此虽然这对于小范围可能没问题,但最好lazy
按如下所示使用,或者stride
如果您的范围很大,请考虑接受的答案。
To avoid creating a large array, use lazy
along with reverse()
. The following test runs efficiently in a Playground showing it is not creating an array with one trillion Int
s!
为避免创建大型数组,请lazy
与 一起使用reverse()
。以下测试在 Playground 中有效运行,表明它没有创建一个具有 1 万亿Int
s的数组!
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 -1
allows you to go backward.
更改增量大小以-1
允许您后退。
for index in stride(from: 4, through: 0, by: -1) {
print(index)
}
// 4
// 3
// 2
// 1
// 0
Note the to
and through
difference.
注意to
和through
区别。
stride: elements of SequenceType
步幅:SequenceType 的元素
Forward by increments of 2
以 2 为增量前进
let animals = ["horse", "cow", "camel", "sheep", "goat"]
I'm using 2
in 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
笔记
@matt has an interesting solutionwhere he defines his own reverse operator and calls it
>>>
. It doesn't take much code to define and is used like this:for index in 5>>>0 { print(index) } // 4 // 3 // 2 // 1 // 0
@matt 有一个有趣的解决方案,他定义了自己的反向运算符并将其称为
>>>
。不需要太多代码来定义和使用如下:for index in 5>>>0 { print(index) } // 4 // 3 // 2 // 1 // 0
回答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 ClosedRange
reversed()
method
#1. 使用ClosedRange
reversed()
方法
ClosedRange
has 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 Range
reversed()
method:
作为替代方案,您可以使用Range
reversed()
方法:
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
first
and repeated lazy applications ofnext
.
返回由 的
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 AnyIterator
init(_:)
initializer
#4. 使用AnyIterator
init(_:)
初始化程序
AnyIterator
has 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 Int
and 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 to
value:
如果要包含该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(Array
or 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 :
输出 :
##代码##