mirror of
https://github.com/nim-lang/Nim.git
synced 2025-12-28 17:04:41 +00:00
Add min/max overloads with comparison functions (#23595)
`min`, `max`, `minmax`, `minIndex` and `maxIndex`
This commit is contained in:
committed by
GitHub
parent
b50ab7a5c9
commit
59ceff4f1a
@@ -34,7 +34,7 @@ errors.
|
||||
[//]: # "Changes:"
|
||||
|
||||
- `std/math` The `^` symbol now supports floating-point as exponent in addition to the Natural type.
|
||||
|
||||
- `min`, `max`, and `sequtils`' `minIndex`, `maxIndex` and `minmax` for `openArray`s now accept a comparison function.
|
||||
- `system.substr` implementation now uses `copymem` (wrapped C `memcpy`) for copying data, if available at compilation.
|
||||
- `system.newStringUninit` is now considered free of side-effects allowing it to be used with `--experimental:strictFuncs`.
|
||||
|
||||
|
||||
@@ -231,6 +231,18 @@ func deduplicate*[T](s: openArray[T], isSorted: bool = false): seq[T] =
|
||||
for itm in items(s):
|
||||
if not result.contains(itm): result.add(itm)
|
||||
|
||||
proc min*[T](x: openArray[T], cmp: proc(a, b: T): int): T {.effectsOf: cmp.} =
|
||||
## The minimum value of `x`.
|
||||
result = x[0]
|
||||
for i in 1..high(x):
|
||||
if cmp(x[i], result) < 0: result = x[i]
|
||||
|
||||
proc max*[T](x: openArray[T], cmp: proc(a, b: T): int): T {.effectsOf: cmp.} =
|
||||
## The maximum value of `x`.
|
||||
result = x[0]
|
||||
for i in 1..high(x):
|
||||
if cmp(result, x[i]) < 0: result = x[i]
|
||||
|
||||
func minIndex*[T](s: openArray[T]): int {.since: (1, 1).} =
|
||||
## Returns the index of the minimum value of `s`.
|
||||
## `T` needs to have a `<` operator.
|
||||
@@ -248,6 +260,20 @@ func minIndex*[T](s: openArray[T]): int {.since: (1, 1).} =
|
||||
for i in 1..high(s):
|
||||
if s[i] < s[result]: result = i
|
||||
|
||||
func minIndex*[T](s: openArray[T], cmp: proc(a, b: T): int): int {.effectsOf: cmp.} =
|
||||
## Returns the index of the minimum value of `s`.
|
||||
runnableExamples:
|
||||
import std/sugar
|
||||
|
||||
let s1 = @["foo","bar", "hello"]
|
||||
let s2 = @[2..4, 1..3, 6..10]
|
||||
assert minIndex(s1, proc (a, b: string): int = a.len - b.len) == 0
|
||||
assert minIndex(s2, (a, b) => a.a - b.a) == 1
|
||||
|
||||
for i in 1..high(s):
|
||||
if cmp(s[i], s[result]) < 0: result = i
|
||||
|
||||
|
||||
func maxIndex*[T](s: openArray[T]): int {.since: (1, 1).} =
|
||||
## Returns the index of the maximum value of `s`.
|
||||
## `T` needs to have a `<` operator.
|
||||
@@ -265,15 +291,35 @@ func maxIndex*[T](s: openArray[T]): int {.since: (1, 1).} =
|
||||
for i in 1..high(s):
|
||||
if s[i] > s[result]: result = i
|
||||
|
||||
func maxIndex*[T](s: openArray[T], cmp: proc(a, b: T): int): int {.effectsOf: cmp.} =
|
||||
## Returns the index of the maximum value of `s`.
|
||||
runnableExamples:
|
||||
import std/sugar
|
||||
|
||||
let s1 = @["foo","bar", "hello"]
|
||||
let s2 = @[2..4, 1..3, 6..10]
|
||||
assert maxIndex(s1, proc (a, b: string): int = a.len - b.len) == 2
|
||||
assert maxIndex(s2, (a, b) => a.a - b.a) == 2
|
||||
|
||||
for i in 1..high(s):
|
||||
if cmp(s[result], s[i]) < 0: result = i
|
||||
|
||||
func minmax*[T](x: openArray[T]): (T, T) =
|
||||
## The minimum and maximum values of `x`. `T` needs to have a `<` operator.
|
||||
var l = x[0]
|
||||
var h = x[0]
|
||||
for i in 1..high(x):
|
||||
if x[i] < l: l = x[i]
|
||||
if h < x[i]: h = x[i]
|
||||
elif h < x[i]: h = x[i]
|
||||
result = (l, h)
|
||||
|
||||
func minmax*[T](x: openArray[T], cmp: proc(a, b: T): int): (T, T) {.effectsOf: cmp.} =
|
||||
## The minimum and maximum values of `x`.
|
||||
result = (x[0], x[0])
|
||||
for i in 1..high(x):
|
||||
if cmp(x[i], result[0]) < 0: result[0] = x[i]
|
||||
elif cmp(result[1], x[i]) < 0: result[1] = x[i]
|
||||
|
||||
|
||||
template zipImpl(s1, s2, retType: untyped): untyped =
|
||||
proc zip*[S, T](s1: openArray[S], s2: openArray[T]): retType =
|
||||
|
||||
Reference in New Issue
Block a user