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












8















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_dict.get)


Which would return the key 2.



How can I do the same in julia ?



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


The latter returns 1=>20 instead of 2=>10 or 2.










share|improve this question























  • indmin() or findmin() should work. Don't know why minimum() does the wrong thing...

    – daycaster
    Oct 13 '15 at 20:59











  • findmin doesn't work actually; it even gives a strange result in this case: (1=>20,16)

    – David P. Sanders
    Oct 13 '15 at 21:06











  • @DavidP.Sanders Strange, I get (10,2).

    – daycaster
    Oct 13 '15 at 21:33






  • 2





    @daycaster minimum iterates Pairs, which compare lexicographically. Therefore, and because here the keys are unique, minimum(x) returns the contained Pair with the lowest key. And indmin returns the index, which is different from the key.

    – user4235730
    Oct 13 '15 at 22:17











  • There is now an issue about this in the Julia repo: github.com/JuliaLang/julia/issues/14672

    – Nicolas Payette
    Apr 19 '17 at 14:44
















8















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_dict.get)


Which would return the key 2.



How can I do the same in julia ?



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


The latter returns 1=>20 instead of 2=>10 or 2.










share|improve this question























  • indmin() or findmin() should work. Don't know why minimum() does the wrong thing...

    – daycaster
    Oct 13 '15 at 20:59











  • findmin doesn't work actually; it even gives a strange result in this case: (1=>20,16)

    – David P. Sanders
    Oct 13 '15 at 21:06











  • @DavidP.Sanders Strange, I get (10,2).

    – daycaster
    Oct 13 '15 at 21:33






  • 2





    @daycaster minimum iterates Pairs, which compare lexicographically. Therefore, and because here the keys are unique, minimum(x) returns the contained Pair with the lowest key. And indmin returns the index, which is different from the key.

    – user4235730
    Oct 13 '15 at 22:17











  • There is now an issue about this in the Julia repo: github.com/JuliaLang/julia/issues/14672

    – Nicolas Payette
    Apr 19 '17 at 14:44














8












8








8


1






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_dict.get)


Which would return the key 2.



How can I do the same in julia ?



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


The latter returns 1=>20 instead of 2=>10 or 2.










share|improve this question














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_dict.get)


Which would return the key 2.



How can I do the same in julia ?



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


The latter returns 1=>20 instead of 2=>10 or 2.







dictionary julia






share|improve this question













share|improve this question











share|improve this question




share|improve this question










asked Oct 13 '15 at 20:21









tsschtssch

544618




544618













  • indmin() or findmin() should work. Don't know why minimum() does the wrong thing...

    – daycaster
    Oct 13 '15 at 20:59











  • findmin doesn't work actually; it even gives a strange result in this case: (1=>20,16)

    – David P. Sanders
    Oct 13 '15 at 21:06











  • @DavidP.Sanders Strange, I get (10,2).

    – daycaster
    Oct 13 '15 at 21:33






  • 2





    @daycaster minimum iterates Pairs, which compare lexicographically. Therefore, and because here the keys are unique, minimum(x) returns the contained Pair with the lowest key. And indmin returns the index, which is different from the key.

    – user4235730
    Oct 13 '15 at 22:17











  • There is now an issue about this in the Julia repo: github.com/JuliaLang/julia/issues/14672

    – Nicolas Payette
    Apr 19 '17 at 14:44



















  • indmin() or findmin() should work. Don't know why minimum() does the wrong thing...

    – daycaster
    Oct 13 '15 at 20:59











  • findmin doesn't work actually; it even gives a strange result in this case: (1=>20,16)

    – David P. Sanders
    Oct 13 '15 at 21:06











  • @DavidP.Sanders Strange, I get (10,2).

    – daycaster
    Oct 13 '15 at 21:33






  • 2





    @daycaster minimum iterates Pairs, which compare lexicographically. Therefore, and because here the keys are unique, minimum(x) returns the contained Pair with the lowest key. And indmin returns the index, which is different from the key.

    – user4235730
    Oct 13 '15 at 22:17











  • There is now an issue about this in the Julia repo: github.com/JuliaLang/julia/issues/14672

    – Nicolas Payette
    Apr 19 '17 at 14:44

















indmin() or findmin() should work. Don't know why minimum() does the wrong thing...

– daycaster
Oct 13 '15 at 20:59





indmin() or findmin() should work. Don't know why minimum() does the wrong thing...

– daycaster
Oct 13 '15 at 20:59













findmin doesn't work actually; it even gives a strange result in this case: (1=>20,16)

– David P. Sanders
Oct 13 '15 at 21:06





findmin doesn't work actually; it even gives a strange result in this case: (1=>20,16)

– David P. Sanders
Oct 13 '15 at 21:06













@DavidP.Sanders Strange, I get (10,2).

– daycaster
Oct 13 '15 at 21:33





@DavidP.Sanders Strange, I get (10,2).

– daycaster
Oct 13 '15 at 21:33




2




2





@daycaster minimum iterates Pairs, which compare lexicographically. Therefore, and because here the keys are unique, minimum(x) returns the contained Pair with the lowest key. And indmin returns the index, which is different from the key.

– user4235730
Oct 13 '15 at 22:17





@daycaster minimum iterates Pairs, which compare lexicographically. Therefore, and because here the keys are unique, minimum(x) returns the contained Pair with the lowest key. And indmin returns the index, which is different from the key.

– user4235730
Oct 13 '15 at 22:17













There is now an issue about this in the Julia repo: github.com/JuliaLang/julia/issues/14672

– Nicolas Payette
Apr 19 '17 at 14:44





There is now an issue about this in the Julia repo: github.com/JuliaLang/julia/issues/14672

– Nicolas Payette
Apr 19 '17 at 14:44












4 Answers
4






active

oldest

votes


















6














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) !






share|improve this answer



















  • 1





    I think it should be guaranteed that the keys and values iterator return elements in the same order. The order itself is undefined, but it'd be pretty crazy if they did something different from each other.

    – Matt B.
    Oct 14 '15 at 4:43






  • 1





    @MattB I don't think you should rely on this. As long as it's not documented, this is an implementation detail. But I agree that this should be guaranteed.

    – user4235730
    Oct 14 '15 at 19:15






  • 1





    Let's document it, then. Care to submit a pull request?

    – Matt B.
    Oct 14 '15 at 19:38











  • This can be written without the collects, which will presumably be much faster: d.keys[indmin(values(d))]. However, d.keys is an internal data structure.

    – David P. Sanders
    Oct 15 '15 at 12:53








  • 1





    necroedit: As of Julia 1.0, indmin() is argmin().

    – daycaster
    Jan 8 at 22:53



















8














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.






share|improve this answer


























  • a version without unicode and working for empty Dicts: reduce((x, y) -> (isa(x,Void) || (d[x] > d[y])) ? y : x, nothing, keys(d))

    – Dan Getz
    Oct 14 '15 at 3:40








  • 1





    Very nice comparison. I like the use of next to get the first value in the dictionary, even if the syntax is not elegant!

    – David P. Sanders
    Oct 15 '15 at 12:48











  • d.keys[indmin(values(d))] is very slightly slower than the explicit loop, but 3 times faster than the other short options. (However, d.keys is an internal data structure.)

    – David P. Sanders
    Oct 15 '15 at 13:01











  • Any idea, why isn't m4 part of any julia library?

    – alvas
    Mar 30 '17 at 8:14



















3














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)





share|improve this answer





















  • 1





    (I have removed my other comment as it is now obsolete.) But doesn't this have type-stability problems as well, for instance if d::Dict{Int, Int}? Isn't then the comparison between Int and either Int or Float? Am I missing something?

    – user4235730
    Oct 14 '15 at 18:50











  • Ah, I see what you mean. I thought you meant that the output of the function was not type stable, but you mean that minkey and minval change type during the function. I'll give it another go...

    – David P. Sanders
    Oct 14 '15 at 19:03











  • Thanks. Fixed to use typemax. This will work for any numeric types, but not e.g. for any kind of Strings. It's surprisingly difficult to make this general! The reduce solution does work for that case, though.

    – David P. Sanders
    Oct 14 '15 at 19:08











  • Agreed, this is why I only consider the non-empty case in my solution ;).

    – user4235730
    Oct 14 '15 at 19:18



















1














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.






share|improve this answer























    Your Answer






    StackExchange.ifUsing("editor", function () {
    StackExchange.using("externalEditor", function () {
    StackExchange.using("snippets", function () {
    StackExchange.snippets.init();
    });
    });
    }, "code-snippets");

    StackExchange.ready(function() {
    var channelOptions = {
    tags: "".split(" "),
    id: "1"
    };
    initTagRenderer("".split(" "), "".split(" "), channelOptions);

    StackExchange.using("externalEditor", function() {
    // Have to fire editor after snippets, if snippets enabled
    if (StackExchange.settings.snippets.snippetsEnabled) {
    StackExchange.using("snippets", function() {
    createEditor();
    });
    }
    else {
    createEditor();
    }
    });

    function createEditor() {
    StackExchange.prepareEditor({
    heartbeatType: 'answer',
    autoActivateHeartbeat: false,
    convertImagesToLinks: true,
    noModals: true,
    showLowRepImageUploadWarning: true,
    reputationToPostImages: 10,
    bindNavPrevention: true,
    postfix: "",
    imageUploader: {
    brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
    contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
    allowUrls: true
    },
    onDemand: true,
    discardSelector: ".discard-answer"
    ,immediatelyShowMarkdownHelp:true
    });


    }
    });














    draft saved

    draft discarded


















    StackExchange.ready(
    function () {
    StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f33111909%2fjulia-how-to-find-the-key-for-the-min-max-value-of-a-dict%23new-answer', 'question_page');
    }
    );

    Post as a guest















    Required, but never shown

























    4 Answers
    4






    active

    oldest

    votes








    4 Answers
    4






    active

    oldest

    votes









    active

    oldest

    votes






    active

    oldest

    votes









    6














    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) !






    share|improve this answer



















    • 1





      I think it should be guaranteed that the keys and values iterator return elements in the same order. The order itself is undefined, but it'd be pretty crazy if they did something different from each other.

      – Matt B.
      Oct 14 '15 at 4:43






    • 1





      @MattB I don't think you should rely on this. As long as it's not documented, this is an implementation detail. But I agree that this should be guaranteed.

      – user4235730
      Oct 14 '15 at 19:15






    • 1





      Let's document it, then. Care to submit a pull request?

      – Matt B.
      Oct 14 '15 at 19:38











    • This can be written without the collects, which will presumably be much faster: d.keys[indmin(values(d))]. However, d.keys is an internal data structure.

      – David P. Sanders
      Oct 15 '15 at 12:53








    • 1





      necroedit: As of Julia 1.0, indmin() is argmin().

      – daycaster
      Jan 8 at 22:53
















    6














    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) !






    share|improve this answer



















    • 1





      I think it should be guaranteed that the keys and values iterator return elements in the same order. The order itself is undefined, but it'd be pretty crazy if they did something different from each other.

      – Matt B.
      Oct 14 '15 at 4:43






    • 1





      @MattB I don't think you should rely on this. As long as it's not documented, this is an implementation detail. But I agree that this should be guaranteed.

      – user4235730
      Oct 14 '15 at 19:15






    • 1





      Let's document it, then. Care to submit a pull request?

      – Matt B.
      Oct 14 '15 at 19:38











    • This can be written without the collects, which will presumably be much faster: d.keys[indmin(values(d))]. However, d.keys is an internal data structure.

      – David P. Sanders
      Oct 15 '15 at 12:53








    • 1





      necroedit: As of Julia 1.0, indmin() is argmin().

      – daycaster
      Jan 8 at 22:53














    6












    6








    6







    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) !






    share|improve this answer













    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) !







    share|improve this answer












    share|improve this answer



    share|improve this answer










    answered Oct 14 '15 at 3:28









    Dan GetzDan Getz

    12.1k11332




    12.1k11332








    • 1





      I think it should be guaranteed that the keys and values iterator return elements in the same order. The order itself is undefined, but it'd be pretty crazy if they did something different from each other.

      – Matt B.
      Oct 14 '15 at 4:43






    • 1





      @MattB I don't think you should rely on this. As long as it's not documented, this is an implementation detail. But I agree that this should be guaranteed.

      – user4235730
      Oct 14 '15 at 19:15






    • 1





      Let's document it, then. Care to submit a pull request?

      – Matt B.
      Oct 14 '15 at 19:38











    • This can be written without the collects, which will presumably be much faster: d.keys[indmin(values(d))]. However, d.keys is an internal data structure.

      – David P. Sanders
      Oct 15 '15 at 12:53








    • 1





      necroedit: As of Julia 1.0, indmin() is argmin().

      – daycaster
      Jan 8 at 22:53














    • 1





      I think it should be guaranteed that the keys and values iterator return elements in the same order. The order itself is undefined, but it'd be pretty crazy if they did something different from each other.

      – Matt B.
      Oct 14 '15 at 4:43






    • 1





      @MattB I don't think you should rely on this. As long as it's not documented, this is an implementation detail. But I agree that this should be guaranteed.

      – user4235730
      Oct 14 '15 at 19:15






    • 1





      Let's document it, then. Care to submit a pull request?

      – Matt B.
      Oct 14 '15 at 19:38











    • This can be written without the collects, which will presumably be much faster: d.keys[indmin(values(d))]. However, d.keys is an internal data structure.

      – David P. Sanders
      Oct 15 '15 at 12:53








    • 1





      necroedit: As of Julia 1.0, indmin() is argmin().

      – daycaster
      Jan 8 at 22:53








    1




    1





    I think it should be guaranteed that the keys and values iterator return elements in the same order. The order itself is undefined, but it'd be pretty crazy if they did something different from each other.

    – Matt B.
    Oct 14 '15 at 4:43





    I think it should be guaranteed that the keys and values iterator return elements in the same order. The order itself is undefined, but it'd be pretty crazy if they did something different from each other.

    – Matt B.
    Oct 14 '15 at 4:43




    1




    1





    @MattB I don't think you should rely on this. As long as it's not documented, this is an implementation detail. But I agree that this should be guaranteed.

    – user4235730
    Oct 14 '15 at 19:15





    @MattB I don't think you should rely on this. As long as it's not documented, this is an implementation detail. But I agree that this should be guaranteed.

    – user4235730
    Oct 14 '15 at 19:15




    1




    1





    Let's document it, then. Care to submit a pull request?

    – Matt B.
    Oct 14 '15 at 19:38





    Let's document it, then. Care to submit a pull request?

    – Matt B.
    Oct 14 '15 at 19:38













    This can be written without the collects, which will presumably be much faster: d.keys[indmin(values(d))]. However, d.keys is an internal data structure.

    – David P. Sanders
    Oct 15 '15 at 12:53







    This can be written without the collects, which will presumably be much faster: d.keys[indmin(values(d))]. However, d.keys is an internal data structure.

    – David P. Sanders
    Oct 15 '15 at 12:53






    1




    1





    necroedit: As of Julia 1.0, indmin() is argmin().

    – daycaster
    Jan 8 at 22:53





    necroedit: As of Julia 1.0, indmin() is argmin().

    – daycaster
    Jan 8 at 22:53













    8














    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.






    share|improve this answer


























    • a version without unicode and working for empty Dicts: reduce((x, y) -> (isa(x,Void) || (d[x] > d[y])) ? y : x, nothing, keys(d))

      – Dan Getz
      Oct 14 '15 at 3:40








    • 1





      Very nice comparison. I like the use of next to get the first value in the dictionary, even if the syntax is not elegant!

      – David P. Sanders
      Oct 15 '15 at 12:48











    • d.keys[indmin(values(d))] is very slightly slower than the explicit loop, but 3 times faster than the other short options. (However, d.keys is an internal data structure.)

      – David P. Sanders
      Oct 15 '15 at 13:01











    • Any idea, why isn't m4 part of any julia library?

      – alvas
      Mar 30 '17 at 8:14
















    8














    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.






    share|improve this answer


























    • a version without unicode and working for empty Dicts: reduce((x, y) -> (isa(x,Void) || (d[x] > d[y])) ? y : x, nothing, keys(d))

      – Dan Getz
      Oct 14 '15 at 3:40








    • 1





      Very nice comparison. I like the use of next to get the first value in the dictionary, even if the syntax is not elegant!

      – David P. Sanders
      Oct 15 '15 at 12:48











    • d.keys[indmin(values(d))] is very slightly slower than the explicit loop, but 3 times faster than the other short options. (However, d.keys is an internal data structure.)

      – David P. Sanders
      Oct 15 '15 at 13:01











    • Any idea, why isn't m4 part of any julia library?

      – alvas
      Mar 30 '17 at 8:14














    8












    8








    8







    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.






    share|improve this answer















    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.







    share|improve this answer














    share|improve this answer



    share|improve this answer








    edited May 23 '17 at 11:46









    Community

    11




    11










    answered Oct 13 '15 at 22:00









    user4235730user4235730

    1,22611529




    1,22611529













    • a version without unicode and working for empty Dicts: reduce((x, y) -> (isa(x,Void) || (d[x] > d[y])) ? y : x, nothing, keys(d))

      – Dan Getz
      Oct 14 '15 at 3:40








    • 1





      Very nice comparison. I like the use of next to get the first value in the dictionary, even if the syntax is not elegant!

      – David P. Sanders
      Oct 15 '15 at 12:48











    • d.keys[indmin(values(d))] is very slightly slower than the explicit loop, but 3 times faster than the other short options. (However, d.keys is an internal data structure.)

      – David P. Sanders
      Oct 15 '15 at 13:01











    • Any idea, why isn't m4 part of any julia library?

      – alvas
      Mar 30 '17 at 8:14



















    • a version without unicode and working for empty Dicts: reduce((x, y) -> (isa(x,Void) || (d[x] > d[y])) ? y : x, nothing, keys(d))

      – Dan Getz
      Oct 14 '15 at 3:40








    • 1





      Very nice comparison. I like the use of next to get the first value in the dictionary, even if the syntax is not elegant!

      – David P. Sanders
      Oct 15 '15 at 12:48











    • d.keys[indmin(values(d))] is very slightly slower than the explicit loop, but 3 times faster than the other short options. (However, d.keys is an internal data structure.)

      – David P. Sanders
      Oct 15 '15 at 13:01











    • Any idea, why isn't m4 part of any julia library?

      – alvas
      Mar 30 '17 at 8:14

















    a version without unicode and working for empty Dicts: reduce((x, y) -> (isa(x,Void) || (d[x] > d[y])) ? y : x, nothing, keys(d))

    – Dan Getz
    Oct 14 '15 at 3:40







    a version without unicode and working for empty Dicts: reduce((x, y) -> (isa(x,Void) || (d[x] > d[y])) ? y : x, nothing, keys(d))

    – Dan Getz
    Oct 14 '15 at 3:40






    1




    1





    Very nice comparison. I like the use of next to get the first value in the dictionary, even if the syntax is not elegant!

    – David P. Sanders
    Oct 15 '15 at 12:48





    Very nice comparison. I like the use of next to get the first value in the dictionary, even if the syntax is not elegant!

    – David P. Sanders
    Oct 15 '15 at 12:48













    d.keys[indmin(values(d))] is very slightly slower than the explicit loop, but 3 times faster than the other short options. (However, d.keys is an internal data structure.)

    – David P. Sanders
    Oct 15 '15 at 13:01





    d.keys[indmin(values(d))] is very slightly slower than the explicit loop, but 3 times faster than the other short options. (However, d.keys is an internal data structure.)

    – David P. Sanders
    Oct 15 '15 at 13:01













    Any idea, why isn't m4 part of any julia library?

    – alvas
    Mar 30 '17 at 8:14





    Any idea, why isn't m4 part of any julia library?

    – alvas
    Mar 30 '17 at 8:14











    3














    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)





    share|improve this answer





















    • 1





      (I have removed my other comment as it is now obsolete.) But doesn't this have type-stability problems as well, for instance if d::Dict{Int, Int}? Isn't then the comparison between Int and either Int or Float? Am I missing something?

      – user4235730
      Oct 14 '15 at 18:50











    • Ah, I see what you mean. I thought you meant that the output of the function was not type stable, but you mean that minkey and minval change type during the function. I'll give it another go...

      – David P. Sanders
      Oct 14 '15 at 19:03











    • Thanks. Fixed to use typemax. This will work for any numeric types, but not e.g. for any kind of Strings. It's surprisingly difficult to make this general! The reduce solution does work for that case, though.

      – David P. Sanders
      Oct 14 '15 at 19:08











    • Agreed, this is why I only consider the non-empty case in my solution ;).

      – user4235730
      Oct 14 '15 at 19:18
















    3














    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)





    share|improve this answer





















    • 1





      (I have removed my other comment as it is now obsolete.) But doesn't this have type-stability problems as well, for instance if d::Dict{Int, Int}? Isn't then the comparison between Int and either Int or Float? Am I missing something?

      – user4235730
      Oct 14 '15 at 18:50











    • Ah, I see what you mean. I thought you meant that the output of the function was not type stable, but you mean that minkey and minval change type during the function. I'll give it another go...

      – David P. Sanders
      Oct 14 '15 at 19:03











    • Thanks. Fixed to use typemax. This will work for any numeric types, but not e.g. for any kind of Strings. It's surprisingly difficult to make this general! The reduce solution does work for that case, though.

      – David P. Sanders
      Oct 14 '15 at 19:08











    • Agreed, this is why I only consider the non-empty case in my solution ;).

      – user4235730
      Oct 14 '15 at 19:18














    3












    3








    3







    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)





    share|improve this answer















    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)






    share|improve this answer














    share|improve this answer



    share|improve this answer








    edited Oct 14 '15 at 19:05

























    answered Oct 13 '15 at 21:05









    David P. SandersDavid P. Sanders

    4,1961818




    4,1961818








    • 1





      (I have removed my other comment as it is now obsolete.) But doesn't this have type-stability problems as well, for instance if d::Dict{Int, Int}? Isn't then the comparison between Int and either Int or Float? Am I missing something?

      – user4235730
      Oct 14 '15 at 18:50











    • Ah, I see what you mean. I thought you meant that the output of the function was not type stable, but you mean that minkey and minval change type during the function. I'll give it another go...

      – David P. Sanders
      Oct 14 '15 at 19:03











    • Thanks. Fixed to use typemax. This will work for any numeric types, but not e.g. for any kind of Strings. It's surprisingly difficult to make this general! The reduce solution does work for that case, though.

      – David P. Sanders
      Oct 14 '15 at 19:08











    • Agreed, this is why I only consider the non-empty case in my solution ;).

      – user4235730
      Oct 14 '15 at 19:18














    • 1





      (I have removed my other comment as it is now obsolete.) But doesn't this have type-stability problems as well, for instance if d::Dict{Int, Int}? Isn't then the comparison between Int and either Int or Float? Am I missing something?

      – user4235730
      Oct 14 '15 at 18:50











    • Ah, I see what you mean. I thought you meant that the output of the function was not type stable, but you mean that minkey and minval change type during the function. I'll give it another go...

      – David P. Sanders
      Oct 14 '15 at 19:03











    • Thanks. Fixed to use typemax. This will work for any numeric types, but not e.g. for any kind of Strings. It's surprisingly difficult to make this general! The reduce solution does work for that case, though.

      – David P. Sanders
      Oct 14 '15 at 19:08











    • Agreed, this is why I only consider the non-empty case in my solution ;).

      – user4235730
      Oct 14 '15 at 19:18








    1




    1





    (I have removed my other comment as it is now obsolete.) But doesn't this have type-stability problems as well, for instance if d::Dict{Int, Int}? Isn't then the comparison between Int and either Int or Float? Am I missing something?

    – user4235730
    Oct 14 '15 at 18:50





    (I have removed my other comment as it is now obsolete.) But doesn't this have type-stability problems as well, for instance if d::Dict{Int, Int}? Isn't then the comparison between Int and either Int or Float? Am I missing something?

    – user4235730
    Oct 14 '15 at 18:50













    Ah, I see what you mean. I thought you meant that the output of the function was not type stable, but you mean that minkey and minval change type during the function. I'll give it another go...

    – David P. Sanders
    Oct 14 '15 at 19:03





    Ah, I see what you mean. I thought you meant that the output of the function was not type stable, but you mean that minkey and minval change type during the function. I'll give it another go...

    – David P. Sanders
    Oct 14 '15 at 19:03













    Thanks. Fixed to use typemax. This will work for any numeric types, but not e.g. for any kind of Strings. It's surprisingly difficult to make this general! The reduce solution does work for that case, though.

    – David P. Sanders
    Oct 14 '15 at 19:08





    Thanks. Fixed to use typemax. This will work for any numeric types, but not e.g. for any kind of Strings. It's surprisingly difficult to make this general! The reduce solution does work for that case, though.

    – David P. Sanders
    Oct 14 '15 at 19:08













    Agreed, this is why I only consider the non-empty case in my solution ;).

    – user4235730
    Oct 14 '15 at 19:18





    Agreed, this is why I only consider the non-empty case in my solution ;).

    – user4235730
    Oct 14 '15 at 19:18











    1














    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.






    share|improve this answer




























      1














      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.






      share|improve this answer


























        1












        1








        1







        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.






        share|improve this answer













        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.







        share|improve this answer












        share|improve this answer



        share|improve this answer










        answered Nov 15 '18 at 3:26









        RamaRama

        112




        112






























            draft saved

            draft discarded




















































            Thanks for contributing an answer to Stack Overflow!


            • Please be sure to answer the question. Provide details and share your research!

            But avoid



            • Asking for help, clarification, or responding to other answers.

            • Making statements based on opinion; back them up with references or personal experience.


            To learn more, see our tips on writing great answers.




            draft saved


            draft discarded














            StackExchange.ready(
            function () {
            StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f33111909%2fjulia-how-to-find-the-key-for-the-min-max-value-of-a-dict%23new-answer', 'question_page');
            }
            );

            Post as a guest















            Required, but never shown





















































            Required, but never shown














            Required, but never shown












            Required, but never shown







            Required, but never shown

































            Required, but never shown














            Required, but never shown












            Required, but never shown







            Required, but never shown







            Popular posts from this blog

            Florida Star v. B. J. F.

            Error while running script in elastic search , gateway timeout

            Adding quotations to stringified JSON object values