2015-08-29 3 views
0

У меня есть быстрый вопрос, который меня немного смущает. Я сделал простую среднюю функцию, которая принимает массив необязательных Интов. Я проверяю, чтобы убедиться, что массив не содержит значения nil, но когда я использую сокращение, я должен принудительно развернуть один из двух элементов в закрытии. Почему это, что я только силой разворачивать второй (в моем случае $ 1!)Unwrapping опционально внутри крышки с использованием уменьшения

func average2(array: [Int?]) -> Double? { 
    let N = Double(array.count) 
    guard N > 0 && !array.contains({$0 == nil}) else { 
     return nil 
    } 

    let sum = Double(array.reduce(0) {$0+$1!}) 
    let average = sum/N 
    return average 
} 

Я знаю, что это просто, но я хотел бы понять это правильно.

ответ

1

Первый параметр reduce - это сумма, которая составляет 0 в начале. Второй - текущий элемент вашего массива, который является необязательным Int и поэтому должен быть развернут.

Ваш вызов уменьшить это делает:

var sum = 0 // Your starting value (an Int) 
for elem in array { 
    sum = sum + elem! // This is the $0 + $1! 
} 

EDIT: Я не мог получить более функциональный подход, чем это работать:

func average(array: [Int?]) -> Double? { 
    guard !array.isEmpty else { return nil } 
    let nonNilArray = array.flatMap{ $0 } 
    guard nonNilArray.count == array.count else { return nil } 
    return Double(nonNilArray.reduce(0, combine: +))/Double(nonNilArray.count) 
} 

Вы также можете отбросить второй guard если вы хотите что-то вроде average([1, 2, nil]), чтобы вернуть 1.5 вместо nil

+0

Так что есть простой способ развернуть его без f orce разворачивание? Конечно, я мог бы сделать цикл for, но я просто тренируюсь с использованием более функциональных методов. –

+0

Большое спасибо. Раньше я не использовал flatmap. Я буду смотреть в него. –

Смежные вопросы