【问题标题】:Using filter on Objects in an Array to find max? [swift]对数组中的对象使用过滤器来查找最大值? [迅速]
【发布时间】:2015-09-26 19:01:52
【问题描述】:

我有一堆对象存储在一个数组中。

他们都有属性:

distanceInSeconds: Int

我想知道是否有一种方法可以使用过滤器或其他数组方法在数组中的所有对象之间找到此属性的最大值?

例如:

var distances: [Distance] = []
var maxDistance = distances.filter(find max)

【问题讨论】:

    标签: ios arrays swift filter filtering


    【解决方案1】:

    这将是 Swifty 方式(通过实现 Comparable):

    class Route : Comparable {
        let distance: Int
    
        init(distance: Int) {
            self.distance = distance
        }
    }
    
    func ==(lhs: Route, rhs: Route) -> Bool {
        return lhs.distance == rhs.distance
    }
    
    func <(lhs: Route, rhs: Route) -> Bool {
        return lhs.distance < rhs.distance
    }
    
    let routes = [
        Route(distance: 4),
        Route(distance: 8),
        Route(distance: 2),
        Route(distance: 7)
    ]
    
    print(routes.maxElement()?.distance)
    

    输出:

    "8"
    

    这适用于 Swift 2。如果您使用的是 Swift 1.2,maxElement(routes) 应该可以工作

    【讨论】:

    • 我做错了什么?当我实现这个类时,它说它不符合协议?
    • @KristoferDoman 也许您在类本身中实现了它,但因为它是操作员要求,所以它必须是全局的。我的代码不适合你吗?已使用 Swift 2 测试
    • 好像没有,不,我是在课外实现的。是否都需要实现它们才能符合协议?
    • 我也在用1.2,不知道这方面有没有大的不同。
    • @KristoferDoman 我真的不知道你的问题是什么,我刚刚在 Playground 中使用 Swift 1.2 进行了尝试,它工作得很好(与 print(maxElement(routes).distance) 交换最后一行)
    【解决方案2】:

    在 Swift 2.0 中,minElement 和 maxElement 现在在空序列的情况下返回可选项,并且现在还有采用 isOrderedBefore 闭包的版本。

        let maxDistance = distances.maxElement { (a, b) -> Bool in
            a.distanceInSeconds < b.distanceInSeconds
        }
    

    【讨论】:

      【解决方案3】:

      #1。序列中的元素类型符合Comparable 协议

      在 Swift 4 中,如果您的序列中的元素类型符合 Comparable 协议,您将能够使用具有以下声明的 max() 方法:

      func max() -> Self.Element?
      

      返回序列中的最大元素。

      用法:

      class Distance: Comparable, CustomStringConvertible {
      
          let distanceInSeconds: Int
          var description: String { return "Distance in Int: \(distanceInSeconds)" }
      
          init(distanceInSeconds: Int) {
              self.distanceInSeconds = distanceInSeconds
          }
      
          static func ==(lhs: Distance, rhs: Distance) -> Bool {
              return lhs.distanceInSeconds == rhs.distanceInSeconds
          }
      
          static func <(lhs: Distance, rhs: Distance) -> Bool {
              return lhs.distanceInSeconds < rhs.distanceInSeconds
          }
      
      }
      
      let distances = [
          Distance(distanceInSeconds: 20),
          Distance(distanceInSeconds: 30),
          Distance(distanceInSeconds: 10)
      ]
      
      let maxDistance = distances.max()
      print(String(describing: maxDistance)) // prints: Optional(Distance in Int: 30)
      

      #2。您的序列中的元素类型不符合Comparable 协议

      在 Swift 4 中,如果序列中的元素类型不符合 Comparable 协议,则必须使用具有以下声明的 max(by:) 方法:

      func max(by areInIncreasingOrder: ((offset: Int, element: Base.Element), (offset: Int, element: Base.Element)) throws -> Bool) rethrows -> (offset: Int, element: Base.Element)?
      

      返回序列中的最大元素,使用给定的谓词作为元素之间的比较。

      用法:

      class Distance: CustomStringConvertible {
      
          let distanceInSeconds: Int
          var description: String { return "Distance in Int: \(distanceInSeconds)" }
      
          init(distanceInSeconds: Int) {
              self.distanceInSeconds = distanceInSeconds
          }
      
      }
      
      let distances = [
          Distance(distanceInSeconds: 20),
          Distance(distanceInSeconds: 30),
          Distance(distanceInSeconds: 10)
      ]
      
      let maxDistance = distances.max (by: { (a, b) -> Bool in
          return a.distanceInSeconds < b.distanceInSeconds
      })
      
      print(String(describing: maxDistance)) // prints: Optional(Distance in Int: 30)
      

      【讨论】:

        【解决方案4】:

        我想你想减少:

        设置:

        struct Distance {
            var distanceInSeconds: Int
        }
        
        var distances: [Distance] = []
        for _ in 1...10 {
            distances += [Distance(distanceInSeconds: Int(arc4random_uniform(100)))]
        }
        

        实施:

        let max = distances.reduce(distances.first) {
            if let left = $0 where left.distanceInSeconds > $1.distanceInSeconds {
                return $0
            } else {
                return $1
            }
        }
        

        【讨论】:

        • 非常接近。应该是:... if $0.distanceInSeconds &lt; $1.distanceInSeconds { ... – 此外,reduce(_) 参数应该是距离对象为 0 distanceInSeconds
        • $0 表示它是 Int 类型,$1 表示它是 Distance 类型,所以我认为存在缺陷。
        • 他放 $0.distanceInSeconds 的地方应该是 $0
        • 谢谢大家,是凭记忆输入的!这个应该可以的!
        • 对不起;后来才意识到reduce参数不应该是0,而是一个距离对象为0的distanceInSeconds
        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2022-11-16
        • 1970-01-01
        • 1970-01-01
        • 2022-07-08
        • 2018-04-08
        • 2015-03-15
        相关资源
        最近更新 更多