julia - How to find the key for the min/max value of a Dict?

前端 未结 4 1818
有刺的猬
有刺的猬 2021-02-20 13:57

I want to find the key corresponding to the min or max value of a dictionary in julia. In Python I would to the following:

my_dict = {1:20, 2:10}
min(my_dict, my         


        
相关标签:
4条回答
  • 2021-02-20 14:29

    If you only need the minimum value, you can use

    minimum(values(my_dict))
    

    If you need the key as well, I don't know a built-in function to do so, but you can easily write it yourself for numeric keys and values:

    function find_min_key{K,V}(d::Dict{K,V})
    
        minkey = typemax(K)
        minval = typemax(V)
    
        for key in keys(d)
            if d[key] < minval
                minkey = key
                minval = d[key]
            end
        end
    
        minkey => minval
    end
    
    my_dict = Dict(1=>20, 2=>10)
    
    find_min_key(my_dict)
    
    0 讨论(0)
  • 2021-02-20 14:31

    You could use reduce like this, which will return the key of the first smallest value in d:

    reduce((x, y) -> d[x] ≤ d[y] ? x : y, keys(d))
    

    This only works for non-empty Dicts, though. (But the notion of the “key of the minimal value of no values” does not really make sense, so that case should usually be handled seperately anyway.)


    Edit regarding efficiency.

    Consider these definitions (none of which handle empty collections)...

    m1(d) = reduce((x, y) -> d[x] ≤ d[y] ? x : y, keys(d))
    
    m2(d) = collect(keys(d))[indmin(collect(values(d)))]
    
    function m3(d)
      minindex(x, y) = d[x] ≤ d[y] ? x : y
      reduce(minindex, keys(d))
    end
    
    function m4(d)
      minkey, minvalue = next(d, start(d))[1]
      for (key, value) in d
        if value < minvalue
          minkey = key
          minvalue = value
        end
      end
      minkey
    end
    

    ...along with this code:

    function benchmark(n)
      d = Dict{Int, Int}(1 => 1)
      m1(d); m2(d); m3(d); m4(d); m5(d)
    
      while length(d) < n
        setindex!(d, rand(-n:n), rand(-n:n))
      end
    
      @time m1(d)
      @time m2(d)
      @time m3(d)
      @time m4(d)
    end
    

    Calling benchmark(10000000) will print something like this:

    1.455388 seconds (30.00 M allocations: 457.748 MB, 4.30% gc time)
    0.380472 seconds (6 allocations: 152.588 MB, 0.21% gc time)
    0.982006 seconds (10.00 M allocations: 152.581 MB, 0.49% gc time)
    0.204604 seconds
    

    From this we can see that m2 (from user3580870's answer) is indeed faster than my original solution m1 by a factor of around 3 to 4, and also uses less memory. This is appearently due to the function call overhead, but also the fact that the λ expression in m1 is not optimized very well. We can alleviate the second problem by defining a helper function like in m3, which is better than m1, but not as good as m2.

    However, m2 still allocates O(n) memory, which can be avoided: If you really need the efficiency, you should use an explicit loop like in m4, which allocates almost no memory and is also faster.

    0 讨论(0)
  • 2021-02-20 14:33

    Here is another way to find Min with Key and Value

    my_dict = Dict(1 => 20, 2 =>10)
    

    findmin(my_dict) gives the output as below

    (10, 2)
    

    to get only key use

    findmin(my_dict)[2]
    

    to get only value use

    findmin(my_dict)[1]
    

    Hope this helps.

    0 讨论(0)
  • 2021-02-20 14:39

    another option is:

    collect(keys(d))[indmin(collect(values(d)))]
    

    it depends on properties of keys and values iterators which are not guaranteed, but in fact work for Dicts (and are guaranteed for OrderedDicts). like the reduce answer, d must be non-empty.

    why mention this, when the reduce, pretty much nails it? it is 3 to 4 times faster (at least on my computer) !

    0 讨论(0)
提交回复
热议问题