Swift 2.2 уменьшает специфичный цикл for в Swift 3

У меня есть задача рефакторинга приложения iOS для Swift 3. Однако есть цикл for в стиле C, который делает больше, чем просто зацикливание массива в обратном направлении (обратное обязательно).

Это пример кода. Принцип тот же.

let array = ["hello", "world", nil, "foo", nil, "bar", "Peter Griffin"]
var threeLetterWords = 0
for var i = array.count-1; i >= 0 && array[i].characters.count == 3; --i, ++threeLetterWords { }
print("Found words: \(threeLetterWords)") // should say `Found words: 2`

Я пробовал с stride(from:through:by:), но не могу увеличить threeLetterWords, так как кажется важным увеличить его в цикле. Любые идеи?


person user3352185    schedule 08.03.2017    source источник
comment
Любой цикл for в стиле C можно заменить циклом while.   -  person vacawama    schedule 08.03.2017
comment
Ваш код подсчитывает количество трехбуквенных слов в конце массива. Он вернет 0 для вашего тестового массива.   -  person vacawama    schedule 08.03.2017
comment
Теперь я полностью понимаю, почему циклы for в стиле C были удалены.   -  person Alexander    schedule 08.03.2017
comment
@Александр, ты прав. Существует какой-то действительно злой код, злоупотребляющий циклами for в стиле C.   -  person vacawama    schedule 08.03.2017


Ответы (3)


Ваш код не считает количество трехбуквенных слов в массиве. Он подсчитывает количество трехбуквенных слов в конце массива. Он вернет 0 для вашего выборочного входного массива.

Когда цикл for в стиле C очень сложен, окончательным резервным решением является преобразование его в цикл while. Любой цикл for в стиле C можно механически преобразовать в эквивалентный цикл while, что означает, что вы можете сделать это, даже если вы не полностью понимаете, что он делает.

Этот цикл for:

for initialization; condition; increment {
    // body
}

эквивалентно:

initialization
while condition {
    // body
    increment
}

Итак, ваш код эквивалентен:

let array = ["hello", "world", nil, "foo", nil, "bar", "Peter Griffin"]
var threeLetterWords = 0

var i = array.count - 1
while i >= 0 && array[i]?.characters.count == 3 {
    i -= 1
    threeLetterWords += 1
}
print("Found words: \(threeLetterWords)") // says `Found words: 0`

Вот как использовать цикл for и guard, чтобы сделать эквивалент вашего кода:

let array = ["hello", "world", nil, "foo", nil, "bar", "Peter Griffin"]
var num3LetterWords = 0

for word in array.reversed() {
    guard word?.characters.count == 3 else { break }
    num3LetterWords += 1
}

print(num3LetterWords)
person vacawama    schedule 08.03.2017

Вы можете использовать свои индексы массива в обратном порядке и добавить предложение where для подсчета символов:

let array = ["hello", "world", nil, "foo", nil, "bar", "Peter Griffin"]
var threeLetterWords = 0

for index in array.indices.reversed() where array[index]?.characters.count == 3 {
    threeLetterWords += 1
}

print("Found words: \(threeLetterWords)") // should say `Found words: 2`
person Leo Dabus    schedule 08.03.2017

Все здесь очень излишне усложняют это.

let words = ["hello", "world", nil, "foo", nil, "bar", "Peter Griffin"]

var num3LetterWords = 0

for word in words.reversed() {
    if (word?.characters.count == 3) { num3LetterWords += 1 }
}

print(num3LetterWords)
person Alexander    schedule 08.03.2017
comment
Это излишне сложный способ выполнения print(words.count). - person vacawama; 08.03.2017
comment
@vacawama хахаха, я забыл скопировать в своем выражении if, исправлено. - person Alexander; 08.03.2017
comment
Вам нужно развернуть: word?.characters.count == 3. Это подсчитывает 3-буквенные слова, но не эквивалентно исходному коду OP, который фактически подсчитывает количество 3-буквенных слов в конце массива. - person vacawama; 08.03.2017
comment
@vacawama Я стремлюсь воспроизвести поведение духа кода, а не слово кода, потому что я подозреваю, что OP просто допустил ошибку, создав этот дерьмовый пример. - person Alexander; 08.03.2017
comment
Я полагаю, что суть их вопроса заключается в том, как мне перевести сложный цикл for в стиле C в нечто эквивалентное в Swift 3, потому что их вопрос признает, что у них есть какой-то сложный пример, которым они не хотели делиться, и составили этот пример как замена. Учитывая, что мы не знаем, насколько сложен их цикл, я решил показать им последний резервный сценарий, который заключается в преобразовании его в цикл while, особенно если вы не понимаете исходный код. - person vacawama; 08.03.2017