It is often useful to calculate the minimum index, maximum index, or sorted indices of an iterable, similar to argmin
, argmax
, argsort
provided by numpy
like modules. The current solutions (AFAIK) are quite slow if compared to what it would be if it were builtin. I doubt I will need to convince anyone about the usefulness of argmin, argmax, argsort, surely everyone here has needed such code, which is why I feel this must have been discussed before? If yes, I have not been able to find any reference to such discussion(s).
Current Solutions
Here are the current solutions worth considering:
min(range(len(finite_iterable)), key=finite_iterable.__getitem__)
# iterates twice, only works with sequences, fast
min(enumerate(finite_iterable), key=itemgetter(1))[0]
# significantly slower than above, which is slower than `min(finite_iterable)`
finite_iterable.index(min(finite_iterable))
# iterates twice, only valid for sequences
Proposal
The proposal is to add a new keyword-only argument index: bool
which, if True, would return something like a IndexedResult/ComparisonResult
object, with roughly the following signature:
@dataclass(frozen=True, slots=True)
class Indexed[T, I: (int, list[int])]:
value: T
index: I
@overload
def min[T: Comparable, V](
iterable: Iterable[T], *, default: V, key, index: Literal[True]
) -> Indexed[T | V, int]: ...
@overload
def min[T: Comparable, *Ts=Comparable](
arg1: T, arg2: T, *args: *Ts, key, index: Literal[True]
) -> Indexed[T, int]: ...
@overload
def sorted[T: Comparable](
iterable: Iterable[T], *, key, reverse, index: Literal[True]
) -> Indexed[list[T], list[int]]: ...
Even though I havenât been able to find reference to past discussion(s) on this topic, I am convinced this must have come up. If yes, I will search harder.