【问题标题】:Using reduce() to build a dictionary in Swift在 Swift 中使用 reduce() 构建字典
【发布时间】:2016-08-01 05:28:21
【问题描述】:

我想使用函数式编程风格构建字典。我的 reduce() 似乎不起作用 - 我收到“致命错误:在展开可选值时意外发现 nil”

func loadMoveToCalendarsRules(calendarIndex: Int) -> [String]? {
//    return something like ["phone call", "buzz", "ring"]
    return NSUserDefaults.standardUserDefaults().objectForKey(generateMoveToCalendarsRules_NSUserDefaultsKey(calendarIndex)) as? [String]
}

// Add indeces to an array of any type
func addIndices<T>(toArray: [T]) -> [(index: Int, value: T)] {
    return Array(zip(toArray.indices, toArray))
}

typealias CalendarRules = [EKCalendar : [String]]?
func buildCalendarRules(cals: [EKCalendar]) -> CalendarRules {
    let sortedCals = cals.sort { $0.title.lowercaseString < $1.title.lowercaseString }

    // build move to cal rules.
    let indexedCalList = addIndices(sortedCals)
    // go through the sorted calendars and build a dictionary that associates each calendar with a string array. (These are keywords that apply to the given calendar.)
    let calendarRules = indexedCalList.reduce(nil as CalendarRules) {
        accumulator, nextValue in
        var retVal: [EKCalendar : [String]]? = accumulator
        // if there are values found in NSUserDefaults for this calendar index then retrieve them.
        if let rulesForCurrentCal = loadMoveToCalendarsRules(nextValue.index) {
            retVal![nextValue.value] = rulesForCurrentCal       // fatal error: unexpectedly found nil while unwrapping an Optional value
        }
        return retVal
    }

    print("------------ built calendar rules -------------")
    print(Array(arrayLiteral: calendarRules?.keys))
    print(Array(arrayLiteral: calendarRules?.values))

    return calendarRules
}

【问题讨论】:

    标签: swift dictionary functional-programming reduce


    【解决方案1】:

    您的retVal 是可选的,以nil(您传入的初始值)开头,但您正在使用retVal! 强制解包它。你可以只使用[:](一个空字典)作为初始值,然后retVal就不需要是可选的了。

    【讨论】:

      【解决方案2】:

      您从nil 开始,并且从不实例化CalendarRules 字典,因此尝试使用! 对其进行强制解包将失败。相反,测试它是否为nil,如果是,则实例化一个。

      在开始之前,我首先建议将日历规则定义为非可选类型。这样可以让事情变得不那么混乱:

      typealias CalendarRules = [EKCalendar : [String]]
      

      然后,您可以在需要时使用nil-coalescing 运算符?? 来实例化CalendarRules 对象:

      let calendarRules = indexedCalList.reduce(nil as CalendarRules?) { accumulator, nextValue in
          if let rulesForCurrentCal = loadMoveToCalendarsRules(nextValue.index) {
              var retVal = accumulator ?? CalendarRules()
              retVal[nextValue.value] = rulesForCurrentCal
              return retVal
          }
          return accumulator
      }
      

      让我感到震惊的是,可能有更有效的方法,但这应该可以解决您的“意外发现 nil”错误。

      【讨论】:

        猜你喜欢
        • 2018-06-10
        • 2021-12-10
        • 2014-12-22
        • 1970-01-01
        • 2018-08-19
        • 2021-02-27
        • 2016-12-02
        • 2021-08-08
        • 2014-07-26
        相关资源
        最近更新 更多