Julia 自定义订单的最大值

Julia 自定义订单的最大值,julia,Julia,我有一个如下所示的数组: julia> list = [(x, rand(0:9), rand(0:9)) for x in 1:5] 5-element Array{Tuple{Int64,Int64,Int64},1}: (1, 7, 2) (2, 1, 3) (3, 4, 7) (4, 4, 8) (5, 8, 3) 我想在列表中找到第三个值最大的元素。如果我只是执行最大值(列表),它将使用默认的(词典)顺序,这不是我想要的: julia> maximum(list

我有一个如下所示的数组:

julia> list = [(x, rand(0:9), rand(0:9)) for x in 1:5]
5-element Array{Tuple{Int64,Int64,Int64},1}:
 (1, 7, 2)
 (2, 1, 3)
 (3, 4, 7)
 (4, 4, 8)
 (5, 8, 3)
我想在列表中找到第三个值最大的元素。如果我只是执行
最大值(列表)
,它将使用默认的(词典)顺序,这不是我想要的:

julia> maximum(list)
(5, 8, 3)
如果对整个列表进行排序,我可以使用自定义的
by
转换/谓词:

julia> sort(list, by=x->x[3], rev=true)
5-element Array{Tuple{Int64,Int64,Int64},1}:
 (4, 4, 8)
 (3, 4, 7)
 (2, 1, 3)
 (5, 8, 3)
 (1, 7, 2)
但是这需要做很多额外的工作-我只需要第一个值-但是它似乎不支持
by
关键字参数:

julia> maximum(list, by=x->x[3])
ERROR: MethodError: no method matching maximum(::Array{Tuple{Int64,Int64,Int64},1}; by=var"#21#22"())
如果我使用“转换”第一个参数函数,我只得到第三个值:

julia> maximum(x->x[3], list)
8

我想要整个元素-
(4,4,8)
。如何执行此操作?

虽然
最大值
不支持
by
关键字,但它支持“transformer”功能。在这种特殊情况下,我们可以找到反向元素的最大值,然后将其反向:

julia> reverse(maximum(reverse, list))
(4, 4, 8)
更一般地说,您可以使用排序基础结构(通过transformers和自定义的lt比较使用其所有花哨的
),而无需使用
partialsort
对整个列表进行实际排序:

julia> partialsort(list, 1, by=x->x[3], rev=true)
(4, 4, 8)
这不是很有效率,但它的功能要强大得多——而且它在整个排序过程中节省了很多。使用更大的向量:

julia> using BenchmarkTools

julia> list = [(x, rand(0:9), rand(0:9)) for x in 1:10_000];

julia> @btime reverse(maximum(reverse, $list));
  7.833 μs (0 allocations: 0 bytes)

julia> @btime partialsort($list, 1, by=x->x[3], rev=true);
  37.772 μs (3 allocations: 234.48 KiB)

julia> @btime sort($list, by=x->x[3], rev=true);
  339.570 μs (5 allocations: 351.81 KiB)

另一种可能是使用
sortperm
获取简化数组的排列索引(仅包含要排序的键),然后使用这些索引对整个数组进行排序:

a = [(x, rand(0:9), rand(0:9)) for x in 1:5]
perm = sortperm(a, by=x->x[3], rev=true)
b = a[perm]
或者,如果您只对最大值感兴趣,请使用

b_max = a[perm[1]]


很好,谢谢!这些都是不错的选择。如果您只需要对整个数组进行最大排序-
sortperm
排序,那么它们会稍微慢一点,但是您可以使用
partialsortperm
来限制作为替代品的工作量。理想情况下,
findmax
/
argmax
也会像
max
那样支持转换器功能,但提前执行该操作需要一个临时数组。这是一个开放的特性请求:也许还值得注意的是,将对
by
关键字的支持添加到
maximum
是一个开放的特性请求-希望有一天它会得到支持!
i_max = findmax(map(x->x[3], a)[2]
b_max = a[i_max]