Как повторить цикл for в обратном порядке в swift?
когда я использую цикл for В Playground, все работало нормально, пока я не изменил первый параметр цикла for на самое высокое значение. (повторяется в порядке убывания)
это ошибка? У кого-нибудь еще она была?
for index in 510..509
{
var a = 10
}
счетчик, отображающий количество итераций, которые будут выполняться, продолжает тикать...
13 ответов:
Xcode 6 beta 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функции-члена. Это глобальные функции, которые возвращают либо aStrideToилиStrideThroughструктуры, которые определяются иначе, чемRangeструктура.в предыдущей версии этого ответа использовался
by()функции-членаRangeструктура, которая была удалена в бета-версии 4. Если вы хотите увидеть, как это работает, проверьте историю правок.
применить обратную функцию к диапазону, чтобы выполнить итерации в обратном направлении:
на 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ответьте, если ваш диапазон большой.
чтобы избежать создания большого массив, используйте
lazyвместе сreverse(). Следующий тест выполняется эффективно на игровой площадке, показывая, что он не создает массив с одним триллиономInts!
обновлено для 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
reversed: элементыSequenceTypelet 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обратите внимание, что, как отметил Бен Лахман в ответ, вы, наверное, хотите сделать
.enumerated().reversed(), а не.reversed().enumerated()(что приведет к увеличению индексов).шаг: цифры
Stride-это способ итерации без использования диапазона. Есть две формы. Комментарии в конце кода показывают какой диапазон версия будет (при условии, что размер инкремент 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Примечание
toиthroughразницы.stride: элементы 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Примечания
@matt has интересным решением где он определяет свой собственный оператор реверса и называет это
>>>. Это не займет много кода, чтобы определить и используется следующим образом:for index in 5>>>0 { print(index) } // 4 // 3 // 2 // 1 // 0
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
для Swift 2.0 и выше вы должны применить обратный на коллекции диапазона
for i in (0 ..< 10).reverse() { // process }Он был переименован .обратная() в Swift 3.0
с Swift 3, в соответствии с вашими потребностями, вы можете выбрать один из восемь следующих реализаций кода игровой площадки для того, чтобы решить вашу проблему.
#1. Используя
CountableClosedRangereversed()метод
CountableClosedRangeимеет метод под названиемreversed().reversed()метод имеет следующее объявление:func reversed() -> ReversedRandomAccessCollection<CountableClosedRange<Bound>>возвращает представление, представляющее элементы коллекции в обратном порядке порядок.
использование:
let reversedRandomAccessCollection = (0 ... 5).reversed() for index in reversedRandomAccessCollection { print(index) } /* Prints: 5 4 3 2 1 0 */
#2. Используя
CountableRangereversed()метод
CountableRangeимеет метод под названиемreversed().reversed()метод имеет следующее объявление:func reversed() -> ReversedRandomAccessCollection<CountableRange<Bound>>возвращает представление, представляющее элементы коллекции в обратном порядке.
использование:
let reversedRandomAccessCollection = (0 ..< 6).reversed() for index in reversedRandomAccessCollection { print(index) } /* Prints: 5 4 3 2 1 0 */
#3. Используя
sequence(first:next:)функциястандартная библиотека Swift предоставляет функцию под названием
sequence(first:next:).sequence(first:next:)есть следующее объявление:func sequence<T>(first: T, next: @escaping (T) -> T?) -> UnfoldSequence<T, (T?, Bool)>возвращает последовательность, сформированную из
firstи повторные ленивые приложенияnext.использование:
let unfoldSequence = sequence(first: 5, next: { > 0 ? - 1 : nil }) for index in unfoldSequence { print(index) } /* Prints: 5 4 3 2 1 0 */
#4. Используя
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возвращает последовательность значений
(self, self + stride, self + 2 * stride, … last)где last-последнее значение в прогрессии меньше или равноend.использование:
let sequence = stride(from: 5, through: 0, by: -1) for index in sequence { print(index) } /* Prints: 5 4 3 2 1 0 */
#5. Используя
stride(from:to:by:)функциистандартная библиотека Swift предоставляет функцию под названием
stride(from:to:by:).stride(from:to:by:)есть следующее объявление:func stride<T>(from start: T, to end: T, by stride: T.Stride) -> StrideTo<T> where T : Strideableвозвращает последовательность значений
(self, self + stride, self + 2 * stride, … last)где last-последнее значение в прогрессии, которое меньшеend.использование:
let sequence = stride(from: 5, to: -1, by: -1) for index in sequence { print(index) } /* Prints: 5 4 3 2 1 0 */
#6. Используя
AnyIteratorinit(_:)инициализатор
AnyIteratorимеет инициализатор под названиемinit(_:).init(_:)есть следующее объявление:init<I>(_ base: I) where I : IteratorProtocol, I.Element == Elementсоздает итератор, который обертывает базовый итератор, но тип которого зависит только от типа элемента базового итератора.
использование:
var index = 5 guard index >= 0 else { fatalError("index must be positive or equal to zero") } let iterator = AnyIterator<Int>({ defer { index = index - 1 } return index >= 0 ? index : nil }) for index in iterator { print(index) } /* Prints: 5 4 3 2 1 0 */#7. Используя
AnyIteratorinit(_:)инициализатор
AnyIteratorимеет инициализатор под названиемinit(_:).init(_:)есть следующее объявление:init(_ body: @escaping () -> AnyIterator.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 */
#8. Использование пользовательского
Intметод расширениявы можете реорганизовать предыдущий код, создав метод расширения для
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 4.0
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 }
если кто-то хочет перебрать массив (
Arrayили вообще любойSequenceType) в обратном направлении. У вас есть несколько дополнительных опций.вы можете
reverse()массив и цикл через него, как обычно. Однако я предпочитаю использоватьenumerate()большую часть времени, так как он выводит кортеж, содержащий объект и его индекс.здесь следует отметить, что важно называть их правильно порядок:
for (index, element) in array.enumerate().reverse()дает индексы в порядке убывания (что я обычно ожидаю). тогда как:
for (index, element) in array.reverse().enumerate()(который является гораздо ближе к )ходит массив назад, но выводит восходящие индексы.
Что касается Swift 2.2, Xcode 7.3 (10, июнь, 2016):
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
var sum1 = 0 for i in 0...100{ sum1 += i } print (sum1) for i in (10...100).reverse(){ sum1 /= i } print(sum1)