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.