在std :: map上使用Lambda函数

时间:2013-08-15 10:37:41

标签: c++ c++11 dictionary lambda std

我想了解如何在C ++中使用 Lambda函数

我正在使用自定义类型,如下所示:

struct my_toy_t {
    uint32_t    id;
    cv::Rect    box;
    cv::Mat     data;
}

typedef std::map<uint32_t, my_toy_t*> my_toy_map_t;

int main() {

    my_toy_map_t input_map;
    my_toy_map_t output_map;

    // Some insertions in input_map...

    my_toy_map_t::iterator it;
    for (it = input_map.begin(); it != input_map.end(); ++it)
    {
        if (check_cond(it->second->box)) {
            output_map.insert(std::make_pair(it->first, it->second));
            input_map.erase(it->first);
        }
    }
    return 0;
}

bool check_cond(cv::Rect box) {
    if (box.area > 100)
        return true;
    else
        return false;
}

可能会注意到my_toy_map_t只是std::map<uint32_t, my_toy_t*>,而check_cond函数会检查一个简单的条件。

是否可以使用Lamba函数翻译此代码(output map中的插入以及input_map如果check_cond返回true的重新调用) ?

3 个答案:

答案 0 :(得分:2)

可能是std::copy_ifstd::inserter

std::copy_if(input_map.begin(),input_map.end(),
             std::inserter(output_map,output_map.end()) ,
    [](const std::pair<uint32_t, my_toy_t*>& x ){ 
                             return (x.second)->box.area > 100;    
                              } 
                );

为了删除我可以想到这个:

my_toy_map_t temp;

std::remove_copy_if(input_map.begin(), input_map.end(), 
                    inserter(temp, temp.end()),
                    [](const std::pair<uint32_t, my_toy_t*>& x ){ 
                                 return (x.second)->box.area > 100;    
                                  } );

input_map.swap(temp);

答案 1 :(得分:2)

首先,不需要指针。如果要避免副本,请使用std::reference_wrapper

其次,您正在迭代容器,并在流程中修改容器。这有未定义的行为:插入/删除操作后,以前的迭代器无效。

您要做的是真正的 过滤过程 :获取传递给定条件的容器元素,并使用它填充另一个容器。<登记/> 使用标准库提供的某些通用算法可以轻松完成。例如,最简单的方法是使用std::copy_if

int main()
{
    std::copy_if( std::begin( input ) , std::end( input ) , std::inserter( output , std::end( output ) ) , [](const std::pair<uint32_t,my_toy_t>& pair ) { return pair->second.box.area > 100; });
}

如您所见,函数std::copy_if()期望可调用实体作为过滤的谓词。在这种情况下,最简单的方法,并且因为您询问如何使用lambda改进过滤,是传递lambda函数。

参考:

答案 2 :(得分:1)

可以将std::for_eachmutable lambda

一起使用
std::for_each(input_map.begin(), input_map.end(),
         [&output_map](const std::pair<uint32_t,my_toy_t*> &it) mutable{
    //   ^^                                                     ^^^^^^^
         if (it.second->box.area > 100)
         {
             output_map.insert(it);
         }
    });

建议:您最好使用smart pointers + STL container而不是原始指针raw pointer + STL container