std :: map <t,bool =“”>,计算真值</t,>

时间:2015-04-15 10:14:07

标签: c++ dictionary lambda countif

我有一张地图:

std::map<std::string, bool> all_triggers_didfire;

我填写它,最后想获得真实值的数量。以下代码有效:

int count_did_fire = std::count_if(
  all_triggers_didfire.begin(), 
  all_triggers_didfire.end(), 
  [](std::pair<std::string, bool> p){return p.second;}
);

有没有比为此定义lambda表达式更简单的方法?

4 个答案:

答案 0 :(得分:12)

我会使用std :: set而不是std :: map。它们在语义上是等价的,但使用std :: set更容易。例如:

std::set<std::string> triggers_that_did_fire;
int count_did_fire = triggers_that_did_fire.size();

当您最初填充triggers_that_did_fire集时,您可以执行以下操作:

triggers_that_did_fire.insert(mystring); //equivalent to setting to "true" in your map
triggers_that_did_fire.remove(mystring); //equivalent to setting to "false"

答案 1 :(得分:9)

有时,一个简单的for循环更清晰:

auto count = 0;
for (auto&& p : all_triggers_didfire)
  if (p.second)
    ++count;

编辑1:我发布原始代码,万一有人看不到编辑记录..

auto count = 0;
for (auto& p : all_triggers_didfire)
  count += p.second;

答案 2 :(得分:4)

您可以使用std::mem_fn将对数据成员的访问权限包装到可调用对象中:

int count_did_fire = std::count_if(
  all_triggers_didfire.begin(), 
  all_triggers_didfire.end(), 
  std::mem_fn(&decltype(all_triggers_didfire)::value_type::second)
);

答案 3 :(得分:0)

  

有没有比为此定义lambda表达式更简单的方法?   

更容易取决于您的意思。这里要记住的一件重要事情是,在C ++中,value_type的{​​{1}}是std::map,而不仅仅是mapped_type。 pair<const key_type,mapped_type>遍历此std::map::iterator,您需要一个包装器来获取密钥或映射类型。

所有C ++标准库算法都适用于迭代器,而std :: map则是迭代器的value_type。因此,要使算法处理映射类型,我们需要将value_type重新映射到映射类型,并为此

  1. 您需要一个名为function的辅助函数(pre C ++ 11)
  2. 你需要一个仿函数
  3. 或者,你需要一个lambda。
  4. 值得注意的是

      

    &#34;如果使用C ++标准库算法会更加愉快   C ++支持lambdas&#34;

    将lambda函数添加到C ++标准的建议,N1958 = 06-002。

    因此,如果您认为您的代码看起来很丑陋,那么您清理代码的意图将会破坏lambda的原始动机。

    因此,如果您打算使用C ++标准库算法,则需要使用lambda(如果需要,如std :: map(句点))。 当然,您仍然可以使用iterative manner重新编写,但这是一个选择和可读性的问题, &#34;可读性在于审稿人的眼中&#34;