Swift 5、自定义对象数组,最小值。不等于同一数组中的其他值

Swift 5, Array of custom object, lowest value. Not equal to other values in same array

如何判断这个数组是否只有一个最小值?

let scoresExampleOne = [2, 2, 3, 4] // return false

let scoresExampleTwo = [2, 3, 3, 5] // return true 

“scoreValues”嵌入在自定义“Player”对象中。

为了这个问题,我只是想简化它。

您只需要迭代您的集合并跟踪最小值以及是否重复:

extension Collection {
    func minElement<T: Comparable>(_ predicate: (Element) -> T) -> (element: Element, single: Bool)? {
        guard var minElement = first else { return nil }
        var min = predicate(minElement)
        var single = true
        for element in dropFirst() {
            let value = predicate(element)
            if value > min { continue }
            if value < min {
                minElement = element
                min = value
                single = true
            } else {
                single = false
            }
        }
        return (minElement, single)
    }
    func min<T: Comparable>(_ predicate: (Element) -> T) -> (min: T, single: Bool)? {
        guard let (element, single) = minElement(predicate) else { return nil }
        return (predicate(element), single)
    }
}

游乐场测试:

struct Player {
    let score: Int
}

let players1: [Player] = [.init(score: 2),
                          .init(score: 2),
                          .init(score: 3),
                          .init(score: 4)]
let players2: [Player] = [.init(score: 2),
                          .init(score: 3),
                          .init(score: 3),
                          .init(score: 5)]

let scoresExampleOne = players1.min(\.score)          // (min 2, single false)
let scoresExampleTwo = players2.min(\.score)          // (min 2, single true)
let scoresExampleThree = players1.minElement(\.score) // ({score 2}, single false)
let scoresExampleFour = players2.minElement(\.score)  // ({score 2}, single true)
func isSingleLowestValue(scores: [Int]) -> Bool {
  guard let min = scores.min() else { return false }

  let minCount = scores.lazy.filter { [=10=] == min }.count
  return minCount == 1
}

Leo 的回答很好,但它是这种extremum 方法的特例。

public extension Sequence {
  /// The first element of the sequence.
  /// - Note: `nil` if the sequence is empty.
  var first: Element? {
    var iterator = makeIterator()
    return iterator.next()
  }

  /// - Parameters:
  ///   - comparable: The property to compare.
  ///   - areSorted: Whether the elements are in order, approaching the extremum.
  func extremum<Comparable: Swift.Comparable>(
    comparing comparable: (Element) throws -> Comparable,
    areSorted: (Comparable, Comparable) throws -> Bool
  ) rethrows -> Extremum<Element>? {
    try first.map { first in
      try dropFirst().reduce(into: .init(value: first, count: 1)) {
        let comparables = (try comparable([=10=].value), try comparable())

        if try areSorted(comparables.0, comparables.1) {
          [=10=] = .init(value: , count: 1)
        } else if (comparables.0 == comparables.1) {
          [=10=].count += 1
        }
      }
    }
  }

  /// - throws: `Extremum<Element>.UniqueError`
  func uniqueMin<Comparable: Swift.Comparable>(
    comparing comparable: (Element) throws -> Comparable
  ) throws -> Extremum<Element> {
    typealias Error = Extremum<Element>.UniqueError

    guard let extremum = try extremum(comparing: comparable, areSorted: >)
    else { throw Error.emptySequence }

    guard extremum.count == 1
    else { throw Error.notUnique(extremum) }

    return extremum
  }
}
public struct Extremum<Value> {
  enum UniqueError: Swift.Error {
    case emptySequence
    case notUnique(Extremum)
  }

  var value: Value
  var count: Int
}