简体   繁体   中英

Using lambda function to find a minimum value in a std::unordered_map

I am trying to find the element with the minimum value in the map. For example, if my map has

 { (1, 12.3),(2, 6.51), (3, 1.24)}

I would like to find the element (3, 1.24) .


I wrote the following code, which tries to write a comparator in the lambda format

std::pair<int, double> min = *std::min_element(
    my_map.begin(), my_map.end(),
    [](std::unordered_map<int, double> a, std::unordered_map<int, double> b) { return a.second < b.second; });

But I got the following errors:

error: no matching function for call to object of type '(lambda at my_code.cpp:118:9)'
            if (__comp(*__i, *__first))
                ^~~~~~
my_code.cpp:116:40: note: in instantiation of function template specialization 'std::__1::min_element<std::__1::__hash_map_iterator<std::__1::__hash_iterator<std::__1::__hash_node<std::__1::__hash_value_type<int, double>, void *> *> >, (lambda at my_code.cpp:118:9)>' requested here
    std::pair<int, double> min = *std::min_element(
                                       ^
my_code.cpp:118:9: note: candidate function not viable: no known conversion from 'std::__1::__hash_map_iterator<std::__1::__hash_iterator<std::__1::__hash_node<std::__1::__hash_value_type<int, double>, void *> *> >::value_type' (aka 'pair<const int, double>') to 'std::unordered_map<int, double>' for 1st argument
        [](std::unordered_map<int, double> a, std::unordered_map<int, double> b) { return a.second < b.second; });
        ^
my_code.cpp:118:9: note: conversion candidate of type 'void (*)(std::unordered_map<int, double>, std::unordered_map<int, double>)'
3 errors generated.

Any idea what I did wrong and what's the proper way to fix this? Thanks!

Your lambda should be binary predicate which takes two pairs of std::pair<const int, double> .

Change the lambda to as follows:

std::pair<int, double> min = *std::min_element(
    my_map.begin(), my_map.end(),
    [](const auto &a, const auto &b) { return a.second < b.second; });

or more explicitly:

std::pair<int, double> min = *std::min_element(
    my_map.begin(), my_map.end(),
    [](const std::pair<const int, double> &a, const std::pair<const int, double> &b) { return a.second < b.second; });
             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^          ^^^^^^^^^^^^^^^^^^^^^^^^^^^^

You are trying to use lambda that accepts maps themselves, not elements of it:

[](std::unordered_map<int, double> a, std::unordered_map<int, double> b)

so it's either (verbose):

[](std::unordered_map<int, double>::value_type a, std::unordered_map<int, double>::value_type b)

or simpler:

[](std::pair<int, double> a, std::pair<int, double> b)

or if you have c++14 or later:

[](auto a, auto b)

you may also consider to pass elements by const reference not to copy them for every iteration.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM