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
}
如何判断这个数组是否只有一个最小值?
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
}