我有一大堆Dict
,它们看起来都是这样的
{
"id": 12345,
"user_id": "6789",
"question_id": "some_question_id",
"correct": "true",
"actions": "...",
"consequentiality": 0,
"timestamp": 1505123456.000
}
我需要按(question_id, user_id, id, consequentiality)
对它们进行排序,其中question_id
移动最慢,consequentiality
移动最慢更快——如果你愿意的话,有点像分组和子分组,但在某些情况下我需要对有序数组执行交换,并且其中大多数往往发生在组之间。我一直在使用 Base.sort
,将不同的函数传递给 by
和 lt
。我想出的最好的办法是将多种排序组合在一起,并将不同的键传递给每个 by
子句,类似于
sort(sort(sort(sort(df, by=x->x["question_id"]), by=x->x["user_id"] ...
你明白了。到目前为止,即使使用MergeSort
等稳定算法,我也无法达到令人满意的稳定排序。
帮忙?
编辑在 by
子句中使用元组有意义吗?但是,如何反转非数字元素的顺序?
最佳答案
这里演示了在注释中使用 lt=...
清理解决方案的方法。请注意,这仅适用于元组,因为它为元组重新定义了isless
。如果有热情,也许这样的东西可以合并到 Julia 或某个包中。
julia> struct RevNext
end
julia> import Base: isless
julia> function isless(t1::Tuple, t2::Tuple)
n1, n2 = length(t1), length(t2)
reverse = false
for i = 1:min(n1, n2)
a, b = t1[i], t2[i]
if !isequal(a, b)
return reverse ? isless(b, a) : isless(a,b)
else
reverse = isa(a,RevNext)
end
end
return n1 < n2
end
WARNING: Method definition isless(Tuple, Tuple) ...
isless (generic function with 53 methods)
要使用它,我们编写sort(M,by=x->(x[:b], RevNext(), x[:a]))
。随机生成向量 M
的示例:
julia> M = [Dict(:a=>rand(),:b=>rand(Bool)) for i=1:10]
10-element Array{Dict{Symbol,Any},1}:
Dict{Symbol,Any}(Pair{Symbol,Any}(:a, 0.735352),Pair{Symbol,Any}(:b, true))
Dict{Symbol,Any}(Pair{Symbol,Any}(:a, 0.537437),Pair{Symbol,Any}(:b, true))
Dict{Symbol,Any}(Pair{Symbol,Any}(:a, 0.314947),Pair{Symbol,Any}(:b, true))
Dict{Symbol,Any}(Pair{Symbol,Any}(:a, 0.9723),Pair{Symbol,Any}(:b, false))
Dict{Symbol,Any}(Pair{Symbol,Any}(:a, 0.605042),Pair{Symbol,Any}(:b, true))
Dict{Symbol,Any}(Pair{Symbol,Any}(:a, 0.256509),Pair{Symbol,Any}(:b, false))
Dict{Symbol,Any}(Pair{Symbol,Any}(:a, 0.133487),Pair{Symbol,Any}(:b, false))
Dict{Symbol,Any}(Pair{Symbol,Any}(:a, 0.320249),Pair{Symbol,Any}(:b, false))
Dict{Symbol,Any}(Pair{Symbol,Any}(:a, 0.409549),Pair{Symbol,Any}(:b, true))
Dict{Symbol,Any}(Pair{Symbol,Any}(:a, 0.421471),Pair{Symbol,Any}(:b, true))
julia> sort(M,by=x->(x[:b], RevNext(), x[:a]))
10-element Array{Dict{Symbol,Any},1}:
Dict{Symbol,Any}(Pair{Symbol,Any}(:a, 0.9723),Pair{Symbol,Any}(:b, false))
Dict{Symbol,Any}(Pair{Symbol,Any}(:a, 0.320249),Pair{Symbol,Any}(:b, false))
Dict{Symbol,Any}(Pair{Symbol,Any}(:a, 0.256509),Pair{Symbol,Any}(:b, false))
Dict{Symbol,Any}(Pair{Symbol,Any}(:a, 0.133487),Pair{Symbol,Any}(:b, false))
Dict{Symbol,Any}(Pair{Symbol,Any}(:a, 0.735352),Pair{Symbol,Any}(:b, true))
Dict{Symbol,Any}(Pair{Symbol,Any}(:a, 0.605042),Pair{Symbol,Any}(:b, true))
Dict{Symbol,Any}(Pair{Symbol,Any}(:a, 0.537437),Pair{Symbol,Any}(:b, true))
Dict{Symbol,Any}(Pair{Symbol,Any}(:a, 0.421471),Pair{Symbol,Any}(:b, true))
Dict{Symbol,Any}(Pair{Symbol,Any}(:a, 0.409549),Pair{Symbol,Any}(:b, true))
Dict{Symbol,Any}(Pair{Symbol,Any}(:a, 0.314947),Pair{Symbol,Any}(:b, true))
关于arrays - 在 Julia 中按多个键对 Dict 数组进行排序,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/46975361/