# Minmax with \`lt\` keyword argument?

**URL:** https://discourse.julialang.org/t/minmax-with-lt-keyword-argument/110398
**Category:** New to Julia
**Created:** [February 19, 2024, 11:21am UTC](https://discourse.julialang.org/t/minmax-with-lt-keyword-argument/110398 "2024-02-19T11:21:16Z")
**Posts on this page:** 12
**Page:** 1

<div class="post-metadata">

### Author: ![putianyi888](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/putianyi888/32/32279_2.png) [@putianyi888](https://discourse.julialang.org/u/putianyi888)
#### Post date: [February 19, 2024, 11:21am UTC](https://discourse.julialang.org/t/minmax-with-lt-keyword-argument/110398/1 "2024-02-19T11:21:16Z")

</div>

Is there a “minmax” that can have a `lt` keyword like what `sort` does? For example, some method that does the following:

```julia
minmax(x, y; lt=isless) = lt(x,y) ? (x,y) : (y,x)

```

---

<div class="post-metadata">

### Author: ![Dan](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/dan/32/42581_2.png) [@Dan](https://discourse.julialang.org/u/Dan)
#### Post date: [February 19, 2024, 11:52am UTC](https://discourse.julialang.org/t/minmax-with-lt-keyword-argument/110398/2 "2024-02-19T11:52:28Z")

</div>

Can you give a small example in running code, or if not possible, an example with small input and the expected output.

---

<div class="post-metadata">

### Author: ![putianyi888](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/putianyi888/32/32279_2.png) [@putianyi888](https://discourse.julialang.org/u/putianyi888)
#### Post date: [February 19, 2024, 12:46pm UTC](https://discourse.julialang.org/t/minmax-with-lt-keyword-argument/110398/3 "2024-02-19T12:46:17Z")

</div>

I’ve updated the op

---

<div class="post-metadata">

### Author: ![barucden](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/barucden/32/26154_2.png) [@barucden](https://discourse.julialang.org/u/barucden)
#### Post date: [February 19, 2024, 1:23pm UTC](https://discourse.julialang.org/t/minmax-with-lt-keyword-argument/110398/4 "2024-02-19T13:23:09Z")

</div>

`min, max = sort([x, y], lt=...)` 😬

I don’t think there is function like that. It seems strange to ask for it though. For example, if you wish to switch the order (`lt=(x, y) -> x ≥ y`), why not simply do `max, min = minmax(x, y)`?

---

<div class="post-metadata">

### Author: ![Dan](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/dan/32/42581_2.png) [@Dan](https://discourse.julialang.org/u/Dan)
#### Post date: [February 19, 2024, 1:24pm UTC](https://discourse.julialang.org/t/minmax-with-lt-keyword-argument/110398/5 "2024-02-19T13:24:09Z")

</div>

```julia
ifelse(lt(x,y), (x,y), (y,x))

```

is very simple and fast.

---

<div class="post-metadata">

### Author: ![roflmaostc](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/roflmaostc/32/30123_2.png) [@roflmaostc](https://discourse.julialang.org/u/roflmaostc)
#### Post date: [February 19, 2024, 1:29pm UTC](https://discourse.julialang.org/t/minmax-with-lt-keyword-argument/110398/6 "2024-02-19T13:29:00Z")

</div>

I would not call this `minmax`, it has different semantics.

But defining and using any function in Julia like this is totally fine.  
But note, the returning type is a Tuple which type depends on the arguments. So this function is not type stable since the return type would depend on the value of the numbers.

```julia
julia> function my_function(x, y; lt=isless)
           return lt(x,y) ? (x,y) : (y,x)
       end
my_function (generic function with 2 methods)

julia> @code_warntype my_function(1, 1.0)
MethodInstance for my_function(::Int64, ::Float64)
  from my_function(x, y; lt) @ Main REPL[12]:1
Arguments
  #self#::Core.Const(my_function)
  x::Int64
  y::Float64
Body::Union{Tuple{Float64, Int64}, Tuple{Int64, Float64}}
1 ─ %1 = Main.:(var"#my_function#3")(Main.isless, #self#, x, y)::Union{Tuple{Float64, Int64}, Tuple{Int64, Float64}}
└── return %1

```

More safe would be to restrict the function arguments to have the same type, or do type promotion to the same type.

```julia
julia> function my_function2(x::T, y::T; lt=isless) where T
           return lt(x,y) ? (x,y) : (y,x)
       end
my_function2 (generic function with 1 method)

julia> my_function2(1, 1.0)
ERROR: MethodError: no method matching my_function2(::Int64, ::Float64)

Closest candidates are:
  my_function2(::T, ::T; lt) where T
   @ Main REPL[16]:1

Stacktrace:
 [1] top-level scope
   @ REPL[17]:1

julia> my_function2(1, 1)
(1, 1)

julia> @code_warntype my_function2(1, 1)
MethodInstance for my_function2(::Int64, ::Int64)
  from my_function2(x::T, y::T; lt) where T @ Main REPL[16]:1
Static Parameters
  T = Int64
Arguments
  #self#::Core.Const(my_function2)
  x::Int64
  y::Int64
Body::Tuple{Int64, Int64}
1 ─ %1 = Main.:(var"#my_function2#5")(Main.isless, #self#, x, y)::Tuple{Int64, Int64}
└── return %1

```

---

<div class="post-metadata">

### Author: ![mikmoore](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/mikmoore/32/31109_2.png) [@mikmoore](https://discourse.julialang.org/u/mikmoore)
#### Post date: [February 19, 2024, 4:14pm UTC](https://discourse.julialang.org/t/minmax-with-lt-keyword-argument/110398/7 "2024-02-19T16:14:26Z")

</div>

It seems like this is maybe looking for something a tad more generic like “sort a short tuple.”

I found this snippet I had lying around. The syntax here is a tad unusual due to outsourcing the ordering to my `makeorder` function, but something like the following might fit your bill (I leave it as an exercise to the reader to write the length=2 version). You can refactor the `makeorder` component to expose the sorting keywords directly within `sorttup`.

```julia
makeorder(;lt=isless,by=identity,rev::Union{Bool,Nothing}=nothing,order::Base.Order.Ordering=Base.Order.Forward,) = Base.Order.ord(lt,by,rev,order)

function sorttup((a,b,c)::NTuple{3},ordr=makeorder())
	# sort 3 values
	a,b = ifelse(Base.lt(ordr,b,a),(b,a),(a,b))
	b,c = ifelse(Base.lt(ordr,c,b),(c,b),(b,c))
	a,b = ifelse(Base.lt(ordr,b,a),(b,a),(a,b))
	return a,b,c
end

function sorttup((a,b,c,d)::NTuple{4},ordr=makeorder())
	# sort 4 values
	a,b = ifelse(Base.lt(ordr,b,a),(b,a),(a,b))
	c,d = ifelse(Base.lt(ordr,d,c),(d,c),(c,d))
	a,c = ifelse(Base.lt(ordr,c,a),(c,a),(a,c))
	b,d = ifelse(Base.lt(ordr,d,b),(d,b),(b,d))
	b,c = ifelse(Base.lt(ordr,c,b),(c,b),(b,c))
	return a,b,c,d
end

```

---

<div class="post-metadata">

### Author: ![roflmaostc](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/roflmaostc/32/30123_2.png) [@roflmaostc](https://discourse.julialang.org/u/roflmaostc)
#### Post date: [February 19, 2024, 4:25pm UTC](https://discourse.julialang.org/t/minmax-with-lt-keyword-argument/110398/8 "2024-02-19T16:25:05Z")

</div>

There is also TupleTools.jl and this sort: [Home · TupleTools.jl](https://jutho.github.io/TupleTools.jl/latest/#TupleTools.sort)

---

<div class="post-metadata">

### Author: ![putianyi888](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/putianyi888/32/32279_2.png) [@putianyi888](https://discourse.julialang.org/u/putianyi888)
#### Post date: [February 19, 2024, 4:56pm UTC](https://discourse.julialang.org/t/minmax-with-lt-keyword-argument/110398/9 "2024-02-19T16:56:06Z")

</div>

TupleTools.jl is slower than SortingNetworks.jl but the latter doesn’t support `lt` or `by`. It’s exactly the motivation of this post though.

---

<div class="post-metadata">

### Author: ![roflmaostc](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/roflmaostc/32/30123_2.png) [@roflmaostc](https://discourse.julialang.org/u/roflmaostc)
#### Post date: [February 19, 2024, 4:58pm UTC](https://discourse.julialang.org/t/minmax-with-lt-keyword-argument/110398/10 "2024-02-19T16:58:16Z")

</div>

You apply this function to some big data?  
Can you share an example for it?

---

<div class="post-metadata">

### Author: ![putianyi888](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/putianyi888/32/32279_2.png) [@putianyi888](https://discourse.julialang.org/u/putianyi888)
#### Post date: [February 19, 2024, 5:02pm UTC](https://discourse.julialang.org/t/minmax-with-lt-keyword-argument/110398/11 "2024-02-19T17:02:37Z")

</div>

Not too big, but kind of low-level. I need to sort intervals before calculating the union of them.

---

<div class="post-metadata">

### Author: ![moble](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/moble/32/23535_2.png) [@moble](https://discourse.julialang.org/u/moble)
#### Post date: [February 19, 2024, 9:25pm UTC](https://discourse.julialang.org/t/minmax-with-lt-keyword-argument/110398/12 "2024-02-19T21:25:10Z")

</div>

Other answers are good; I just want to point out that you may also be interested in

```julia
extrema(f, (x,y))

```

which always uses `<` for comparisons, but allows you to preprocess the input with the function `f`. (Plus it extends nicely to longer collections.) In the trivial case, it compiles down to exactly the same code as other solutions.

Also note that most answers use the tuple `(x, y)` instead of the vector `[x, y]` because the vector would allocate, whereas the tuple will not.
