[ios] 신속하게 for 루프를 역순으로 반복하는 방법은 무엇입니까?

놀이터에서 for 루프를 사용하면 for 루프의 첫 번째 매개 변수가 가장 높은 값으로 변경 될 때까지 모든 것이 잘 작동했습니다. (내림차순으로 인용)

이것이 버그입니까? 다른 사람이 있습니까?

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

실행될 반복 횟수를 표시하는 카운터는 계속 똑딱 거립니다.

여기에 이미지 설명을 입력하십시오



답변

: 엑스 코드 6 베타 4는 하나 이상의 다른 단계의 범위에서 반복하는 두 가지 기능을 추가
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에서 제거 된 구조체 의 by()멤버 함수를 사용했습니다.이 기능이 Range어떻게 작동하는지 보려면 편집 기록을 확인하십시오.


답변

뒤로 반복하는 범위에 역 기능을 적용하십시오.

대한 스위프트 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범위가 큰 경우 허용되는 답변을 고려하는 것이 좋습니다 .


큰 배열을 만들지 않으려면와 lazy함께 사용하십시오 reverse(). 다음 테스트는 놀이터에서 효율적으로 실행되어 1 조 개의 배열을 만들지 않음을 보여줍니다 Int!

테스트:

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

대한 스위프트 2.0 엑스 코드 7 :

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

들어 스위프트 3.0 reverse() 로 이름이 바뀌 었습니다 reversed():

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


답변

스위프트 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

reversed:의 요소 SequenceType

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: 색인이있는 요소

컬렉션을 반복 할 때 인덱스가 필요할 때가 있습니다. 이를 위해 enumerate()튜플을 반환하는을 사용할 수 있습니다 . 튜플의 첫 번째 요소는 색인이고 두 번째 요소는 객체입니다.

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()것입니다.

보폭 : 숫자

보폭은 범위를 사용하지 않고 반복하는 방법입니다. 두 가지 형태가 있습니다. 코드 끝의 주석은 범위 버전이 무엇인지 보여줍니다 (증분 크기가 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 

노트


답변

스위프트 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


답변

Swift 5를 사용하면 필요에 따라 다음 네 가지 놀이터 코드 예제 중 하나를 선택 하여 문제를 해결할 수 있습니다.


#1. ClosedRange reversed()방법을 사용하여

ClosedRange라는 메소드가 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
*/

대안으로 다음 Range reversed()방법 을 사용할 수 있습니다 .

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

for index in reversedCollection {
    print(index)
}

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

# 2. sequence(first:next:)기능 사용

스위프트 표준 라이브러리는 sequence(first:next:). sequence(first:next:)다음과 같은 선언이 있습니다.

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

에서 형성된 시퀀스를 반환 first 지연 응용 프로그램으로 되고 반복next .

용법:

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

for index in unfoldSequence {
    print(index)
}

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

#삼. stride(from:through:by:)기능 사용

Swift Standard Library는라는 기능을 제공합니다 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. 사용AnyIterator init(_:)이니셜 라이저

AnyIterator이니셜 라이저가 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
*/

필요한 경우 확장 메소드를 작성하고 Int반복자를 랩핑하여 이전 코드를 리팩터링 할 수 있습니다 .

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


답변

Swift 2.0 이상에서는 범위 콜렉션에 역을 적용해야합니다

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

Swift 3.0에서 이름이 .reversed ()로 변경되었습니다.


답변

스위프트 4 이상

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