Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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!

like image 428
Edamame Avatar asked Apr 22 '26 02:04

Edamame


2 Answers

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.

like image 172
Slava Avatar answered Apr 23 '26 16:04

Slava


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; });
             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^          ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
like image 44
JeJo Avatar answered Apr 23 '26 15:04

JeJo



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!