【问题标题】:How can I make a extension for array of specific type in Swift如何在 Swift 中为特定类型的数组进行扩展
【发布时间】:2015-08-05 20:36:38
【问题描述】:

说我有:

struct S {
    var num = 0
}

我想实现一个函数 allEqual() 作为Array<S> 的扩展,所以我可以这样做

var s1 = S()
var s2 = S()
var s3 = S()
var equality = [s1,s2,s3].allEqual()

【问题讨论】:

    标签: swift


    【解决方案1】:

    表示具体的类型是S

    extension CollectionType where Generator.Element == S {
    }
    

    CollectionType Protocol

    【讨论】:

    【解决方案2】:

    在最新的 Swift 3.1 中。您可以对具体类型扩展进行相同类型的约束。所以在你的情况下,你可以这样做:

    extension Array where Element == S {
        func allEqual() -> Bool {
            ...
        }
    }
    

    【讨论】:

      【解决方案3】:

      我创建了一个扩展,它可以懒惰地为Elements 为Equatable 的任何SequenceType 工作。在 Swift 中,让你的代码完全按照它可以工作的方式工作是一个很好的做法:为了能够获得所有元素是否相等,它必须是一系列可相等的值。代码如下:

      extension SequenceType where Generator.Element : Equatable {
          var allEqual : Bool {
              var gen = generate()           // Generate the sequence for the first element
              return gen.next().map { fst in // Get first element and map it (when existing)
                  !contains { fst != $0 }    // To whether self doesn't contain any elements unequal to first
              } ?? true                      // When first is nil, return true
          }                                   
      }
      

      或者你也可以做更多的迭代(基本上一样我认为更快?):

      extension SequenceType where Generator.Element : Equatable {
          var allEqual : Bool {
              var gen = generate()
              let first = gen.next()
              return !contains { $0 != first }
          }
      }
      

      您还应该使您的结构符合Equatable 协议,如下所示:

      func ==(lhs: S, rhs: S) -> Bool {
          return lhs.x == rhs.x
      }
      

      因为every value type should be equatable 显然在您的代码中这样做完全有意义。

      这是一些测试代码:

      [S(x: 3), S(x: 3), S(x: 3)].allEqual    // true
      [S(x: 5), S(x: 3), S(x: 3)].allEqual    // false
      [S(x: 5), S(x: 5)].allEqual             // true
      [S(x: 0)].allEqual                      // true
      [S]().allEqual                          // true
      

      注意它是惰性的,这意味着一旦有一个元素不等于第一个元素,它就会返回 false,所以如果你有这样的东西:

      let longList = [S(x: 5)] + [S](count: 100000, repeatedValue: S(x: 4))
          // [{x 5}, {x 4}, {x 4}, {x 4}, {x 4}, {x 4}, {x 4}, ...
      longList.allEqual   // false
      

      将在第二个元素处返回,因为已经存在相等性

      编辑:我之前的功能过于复杂。新的还是懒惰的,只是更短了

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2021-10-17
        • 1970-01-01
        • 1970-01-01
        • 2014-07-24
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多