Развертка необязательного в Swift 4

У меня есть следующий код на игровой площадке:

// Create an empty array of optional integers
var someOptionalInts = [Int?]()

// Create a function squaredSums3 with one argument, i.e. an Array of optional Ints
func squaredSums3(_ someOptionalInts: Int?...)->Int {
    // Create a variable to store the result
    var result = 0

    // Get both the index and the value (at the index) by enumerating through each element in the someOptionalInts array
    for (index, element) in someOptionalInts.enumerated() {
        // If the index of the array modulo 2 is not equal to 0, then square the element at that index and add to result
        if index % 2 != 0 {
            result += element * element
        }
    }

    // Return the result
    return result
}

// Test the code
squaredSums3(1,2,3,nil)

Результат строки += element * element дает следующую ошибку «Значение необязательного типа« Int? не развернуто; вы хотели использовать '!' или '?'?" Я не хочу использовать '!' и я должен проверить на нулевой случай. Я не уверен, где (или даже как, если честно) развернуть необязательный. Предложения?


person Community    schedule 04.09.2018    source источник
comment
Сделать if let: if let unwrappedElement = element { if index %2... {} }? Это основная распаковка. Или вы можете развернуть уже someOptionalInts вместо someOptionalInts, сделать let unwrappedSomeInts = someOptionalInts.flatMap{ $0 } и использовать его для цикла.   -  person Larme    schedule 04.09.2018


Ответы (4)


Все, что вам нужно сделать, это развернуть необязательный:

if let element = element, index % 2 != 0 {
    result += element * element
}

Это будет игнорировать нулевые значения.

Преимущество этого над любым типом сопоставления заключается в том, что вам не нужно проходить массив дополнительно.

person jancakes    schedule 04.09.2018
comment
Хорошо, спасибо! Я новичок в опциях, и они немного сбивают с толку. Я уверен, что я привыкну к ним, поскольку я использую их больше. Благодарю вас! - person ; 04.09.2018
comment
Совершенно никаких проблем. К ним определенно нужно привыкнуть. - person jancakes; 04.09.2018
comment
@MatthewSpire, но ты сказал, что не можешь просто игнорировать те, которые равны нулю! Вот и ты так делай. - person LinusGeffarth; 04.09.2018
comment
@LinusGeffarth Я думаю, он имел в виду, что не может просто отфильтровать их, потому что это сбило бы индексы. Компактная карта превратила бы [1, nil, 2, 3] в [1, 2, 3], и тогда его операция по изменению индекса была бы неправильной. - person jancakes; 04.09.2018
comment
А, наверное, да. - person LinusGeffarth; 04.09.2018
comment
Да, я думаю, @jancakes понял, что я имел в виду. Я ценю обе ваши помощи. Благодарю вас! - person ; 04.09.2018

Если вы хотите исключить нулевые значения из массива, вы можете сжать его:

for (index, element) in (someOptionalInts.compactMap { $0 }).enumerated() {

Тогда element больше не будет необязательным.


Если вместо этого вы хотите рассматривать все значения nil как 0, вы можете сделать:

if index % 2 != 0 {
    result += (element ?? 0) * (element ?? 0)
}
person LinusGeffarth    schedule 04.09.2018
comment
Я не могу исключить нулевые значения из массива. SquaredSums3(1,2,3,nil) должен вернуть 4, что означает, что он учитывает тот факт, что nil находится в массиве, и просто игнорирует его. - person ; 04.09.2018
comment
@MatthewSpire Итак, какова твоя цель? Как вы хотите иметь дело с нулевым значением? Следует ли рассматривать его как 0? - person LinusGeffarth; 04.09.2018

Ошибка появляется, потому что вы должны указать, что делать, если элемент равен нулю

if index % 2 != 0 {
    if let element = element {
        result += element * element
    }
    else {
        // do whatever you want
    }
}
person zheck    schedule 04.09.2018
comment
Нет, им не нужно указывать, что делать, если элемент равен нулю. Все, что им нужно сделать, это развернуть его. - person jancakes; 04.09.2018

Вот как бы я это написал:

for (index, element) in someOptionalInts.enumerated() {
    guard let element = element, index % 2 == 0 else { continue }
    result += element * element
}
// result == 10

Оператор guard означает, что меня интересует только тогда, когда element не равно nil и его index четно.

person Code Different    schedule 04.09.2018