I just did this,
1, 5, 100, 2, 7 becomes 5, 100, 7
1, 2, 18, 19, 5, 4 becomes 2, 19, 5
extension Array where Element: Comparable {
///Simply return the bigger of each pair of (say) integers as we go
///along. (If there's an odd count, of course the last solo one is
///just that value.)
var biggerOfPairs: [Element] {
// var safely: [Element] = []
// if self.count % 2 == 1 { safely.append(Element.min) }
// var result: [Element] = []
// for i in 0..<(safely.count/2) {
// result.append(Swift.max(safely[i * 2], safely[(i * 2) + 1]))
// }
// damnit! ask on SO
var result: [Element] = []
for i in 0..<(self.count/2) {
result.append(Swift.max(self[i * 2], self[(i * 2) + 1]))
}
if self.count % 2 == 1 {
result.append(self[self.count - 1])
}
return result
}
}
(I use the usual trick if you need a list to be in, say, groups of three, just add the appropriate "dud" element(s) on the end, if the size of the list doesn't divide by three; so that you can run an exception-free algorithm. (The "dud" elements might be empty views, zero, nil, or whatever is relevant.) Hence if this extension was just on [Int] you'd make the "dud" one at the end Int.min
.)
but sadly,
It seems hard to believe you would write a Comparable
protocol without a min/max representable concept.
(They have a note in the doco about exceptional concepts like NaN
, but still. Since when could you program along the lines "oh don't worry about corner cases." - !)
Could it be I'm missing something?
(*) Maybe there's a tighter protocol to use that includes a lowest representable value?
FTR at one point an error appeared suggesting (any Comparable).min
, but that didn't seem to pan out (and I don't understand it anyway).
It doesn't make sense for all Comparable
things to have a max
or min
.
There are comparable things that can arbitrarily large, like String
, or BigInt
. The "maximum value" of these types would be very time-consuming to create, and take a lot of memory.
There are comparable things that have multiple "maximum values". For example, a class like
class Foo: Comparable {
var value: Int // this class implements Comparable based on this
// initialiser and operator implementations omitted
}
let x = Foo(value: .max)
let y = Foo(value: .max)
x
and y
are both "maximum values" for Foo
, but these are distinct class instances. In fact, your implementation of biggerOfPairs
could return a Foo
instance that is not in the original array if Foo.min
simply returns a new instance (return Foo(value: .min)
). This is because max
returns the second argument if the two arguments are equal.
Technically this also applies to floating point types, since IEEE 754 allows multiple representations of "infinity", but it is not that much of a problem in practice.
I would recommend creating your own protocol like this:
protocol HasMinMax {
var min: Self { get }
var max: Self { get }
}
FixedWidthInteger
offers the min
and max
properties. FloatingPoint
offers infinity
, and you can use -.infinity
for min
. You can retroactively conform types that conform to FixedWidthInteger
and FloatingPoint
to HasMinMax
, but you cannot directly do
extension FixedWidthInteger: HasMinMax { ... }
extension FloatingPoint: HasMinMax { ... }