Is there any way to use max() and min() based on a function?

This is easily done in, for example, Python, and can be very useful. I have spent quite a bit of time searching documentation and reading forum questions, without finding anything.

Here’s a small example of what I would like to do:

arr = [1,2,3,4,-5]
sqmax = max(arr, by = x -> x^2)

I know this can be done as follows, but it seems like it would make sense for max() to have a by option.

sqmax = sort(arr, by = x -> x^2)[end]

You are looking for what is called maximum in Julia. Take a look at the documentation on max and maximum for more examples.

Welcome to the forum. A question like this is better suited for the “Usage” category.

3 Likes

But still there is no built in maxiumum function offering whats requested.

I’d go with:
findmax(map(x->x^2,arr))

Update: this is only needed if you want the index, which I initially thought was asked.

maximum does take an optional function as its first argument. Try maximum(x -> x^2, arr).

6 Likes

why not:

maximum(arr.^2)

The problem with that is that it creates a temporary array, which can be avoided by passing the function as an argument.

3 Likes

That allocates an intermediate array for the squared array whereas the version from simon does not. It would be nice if we could reduce over a broadcasted array without allocs one day but we’re not there yet.

thanks for the answer, but maximum(f, arr) will return the maximal element in f(arr) rather than in arr.
Is there any keyword of maximum or other functons to “find x in arr s.t. f(x) is maximal”

Example:

xs = [1, 3, 2]; i = argmax([x^2 for x in xs]); println(xs[i])

You can also pass the function to argmax, to avoid the allocation of the intermediate array:

julia> x = [1,3,2]
3-element Vector{Int64}:
 1
 3
 2

julia> argmax(x -> -x^2, x)
1

julia> argmax(x -> x^2, x)
3


4 Likes
julia> findmax(abs2, -3:2)
(9, 1)

the second returned value can be used to index the arr

or just use:

julia> argmax(abs2, -3:2)
-3

which does the indexing for you under the hood

3 Likes
foldl((x,y)->x^2>y^2 ? x : y, arr)

or

foldl((x,y)->ifelse(x^2>y^2 , x , y), arr)
maxby(f,arr)=foldl((x,y)->f(x)>f(y) ? x : y, arr)
1 Like

Yes, for those wondering, this feature was added in Julia v1.7. Quite useful/convenient on occasion.

Open issue up for grabs: Add a `by` keyword to `maximum` and `minimum` · Issue #28210 · JuliaLang/julia · GitHub

(Of course, you could just write your own loop for this, which is perfectly fast.)

1 Like

Thanks! I found out this implementation is new in Julia 1.7. For 1.6 or lower version, it still can be done by a less direct way

data[argmax(f.data)]