Swift - развернуть необязательно в цикле for in с предложением where

У меня есть класс с необязательным членом:

class A {
    var i: Int? = nil
}

Затем у меня есть массив объектов типа A. Некоторые объекты в массиве имеют значение i, некоторые — нет.

Я хочу перебирать объекты в массиве, которые имеют значение для i, одновременно разворачивая необязательное. Я не нашел способа сделать и то, и другое одновременно (я даже не знаю, возможно ли это), что вынуждает меня писать конструкцию if let внутри цикла.
Например:

// a1, a2 have a value for i
let arr: [A] = [a1, a2, a3]
for obj in arr where obj.i != nil {
    // I want to avoid if let, or force unwrapping here
    if let unwrapped = obj.i {
        print(i)
    }
    // let unwrapped = obj.i! ...
}

Возможно ли это в Swift?


person Vince    schedule 06.01.2017    source источник
comment
Вам нужны и obj, и (развернутый) obj.i в теле цикла или только obj.i?   -  person Martin R    schedule 06.01.2017
comment
Мне действительно нужны и obj, и i внутри цикла   -  person Vince    schedule 06.01.2017


Ответы (2)


Я не думаю, что это возможно.

Даже если в вашем цикле есть предложение where, тип obj по-прежнему имеет тип A и поэтому i > по-прежнему остается необязательным.

Чтобы понять, почему это так, подумайте о том факте, что вы можете изменить значение i для объекта obj внутри цикла, поэтому компилятор не уверен, что значение < strong>i действителен до тех пор, пока вы его не развернете.

Вы можете попробовать что-то вроде этого

for obj in arr where obj.i != nil {
  guard let i = obj.i else { continue }

  print( i )
}

но если вы начнете использовать guard, вы также пропустите предложение where

for obj in arr {
   guard let i = obj.i else { continue }

   print( i )
}
person Radu Diță    schedule 06.01.2017
comment
Хорошо, так что мой лучший выбор здесь, похоже, это принудительное развертывание. Я вижу if let внутри цикла как повтор предложения where - person Vince; 06.01.2017
comment
есть что-то, что вы могли бы использовать, вы можете использовать защиту, вы знаете, что условие защиты никогда не будет достигнуто, но вам не нужно оборачивать свой код, если позволить - person Radu Diță; 06.01.2017
comment
Я только что наткнулся на этот вопрос и нашел эту статью, подумал, что должен поделиться ею с будущими поколениями: D using-for-in-loop-519e96b6f330" rel="nofollow noreferrer">medium.com/@rizwan95/ - person ErickES7; 19.10.2019

1. Возможно, вы можете использовать flatMap, чтобы получить значение i, а затем распечатать его.

arr.flatMap{ $0.i }.forEach{ print($0) }

2.или попробуйте простую инструкцию guard

arr.forEach { element in
    guard let i = element.i else { return }
    print(i)
}
person Sai Li    schedule 06.01.2017
comment
flatMap - предпочтительный способ делать такие вещи. Прочтите эту статью о его удивительности natashatherobot.com/swift-2-flatmap. - person Maksym Musiienko; 06.01.2017
comment
Ваш flatMap(_:) не даст вам obj и i внутри цикла — только i. - person Hamish; 06.01.2017