【问题标题】:Swift - Cleaner Syntax for Reducing an Array inside GuardSwift - 用于减少 Guard 内部数组的更简洁语法
【发布时间】:2017-12-31 15:49:16
【问题描述】:

我有一个由两个数组驱动的 UIView:[Float]“数据”和[UIColor]“颜色”。如果视图没有提供正确的数据,我将显示一个空状态,由您在此处看到的保护语句控制:

private func unwrap() -> ([Float], [UIColor]) {
    guard
        let data = data, !data.isEmpty,
        let colors = colors, data.count == colors.count
        else { return ([1], [UIColor.lightGray]) } // empty state

    let total = data.reduce(0) { $0 + $1 }
    if total == 0 { return ([1], [UIColor.lightGray]) }

    return (data, colors)
}

我不喜欢重复使用空状态return ([1], [UIColor.lightGray]) 两次。我尝试在保护语句中添加 data.reduce 调用,例如:

private func unwrap() -> ([Float], [UIColor]) {
    guard
        let data = data, !data.isEmpty,
        let colors = colors, data.count == colors.count,
        data.reduce(0) { $0 + $1 } != 0
        else { return ([1], [UIColor.lightGray]) } // empty state

    return (data, colors)
}

...编译器不理解语法

private func unwrap() -> ([Float], [UIColor]) {
    guard
        let data = data, !data.isEmpty,
        let colors = colors, data.count == colors.count,
        let total = data.reduce(0) { $0 + $1 }, total != 0
        else { return ([1], [UIColor.lightGray]) } // empty state

    return (data, colors)
}

...闭包data.reduce(0) { $0 + $1 } 的结果不是可选的,因此不能包含在保护声明中。

有没有更简洁的方法来做到这一点?

【问题讨论】:

  • 避免使用并行数组;创建一个包含FloatUIColorstruct,然后拥有该结构的数组。这样你的data.count == colors.count 前置条件就会消失,因为它现在由编译器强制执行。
  • @Hamish 确实如此。这是一个 XY 问题。
  • 在这个 UIView 实现的类中,从源数组创建一个结构是不必要的开销,没有任何好处。使实现更复杂,更不优雅。

标签: swift reduce


【解决方案1】:

这是我的简化版:

private func unwrap() -> ([Float], [UIColor]) {
    guard let data = data, let colors = colors,
        data.count == colors.count, data.reduce(0, +) != 0  else {
            return ([1], [UIColor.lightGray])
    } // empty state

    return (data, colors)
}

reduce可以直接使用float的+函数,一个空数组的reduce总是0,所以不需要检查空状态。

【讨论】:

    【解决方案2】:

    想通了。

    private func unwrap() -> ([Float], [UIColor]) {
        guard
            let data = data, !data.isEmpty,
            let colors = colors, data.count == colors.count,
            (data.reduce(0) { $0 + $1 }) != 0
            else { return ([1], [UIColor.lightGray]) } // empty state
    
        return (data, colors)
    }
    

    【讨论】:

      【解决方案3】:

      如何让你的返回值成为一个计算变量:

      private func unwrap() -> ([Float], [UIColor]) {
          var emptyVal: ([Float], [UIColor]) {
              return ([1], [UIColor.lightGray])
          }
      
          guard
              let data = data, !data.isEmpty,
              let colors = colors, data.count == colors.count
              else { return emptyVal } // empty state
      
          let total = data.reduce(0) { $0 + $1 }
          if total == 0 { return emptyVal }
      
          return (data, colors)
      }
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2023-04-09
        • 1970-01-01
        • 2017-10-04
        • 2022-01-24
        相关资源
        最近更新 更多