Std:: map <T, bool>, значения count, которые являются истинными

У меня есть карта:

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;}
);

Есть ли более простой способ, чем определить лямбда-выражение для этого?

Ответы

Ответ 1

Я бы использовал 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"

Ответ 2

Иногда простой цикл for немного ясен:

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

EDIT 1: я выложу исходный код, если кто-то не сможет увидеть историю изменений.

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

Ответ 3

Вы можете использовать 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)
);

Ответ 4

Есть ли более простой способ, чем определить лямбда-выражение для этого? Нет.

Зависит от того, что вы имеете в виду, проще. Здесь важно помнить, что в С++ value_type std::map есть pair<const key_type,mapped_type>, а не только тип mapped_type. std::map::iterator выполняет итерацию по этому value_type, и вам нужна оболочка для извлечения ключа или отображаемого типа.

Все алгоритмы стандартной библиотеки С++ работают на итераторах, а для std:: map - это итератор для value_type. Поэтому для того, чтобы алгоритмы работали над отображенным типом, нам нужно повторно отобразить тип value_type для сопоставленного типа, и для этого либо

  • Вам нужна вспомогательная именованная функция (pre С++ 11)
  • Вам понадобится функтор
  • Или вам понадобится лямбда.

Стоит отметить, что

"Алгоритмы стандартной библиотеки С++ были бы гораздо приятнее использовать, если У С++ была поддержка лямбда"

Предложение о добавлении лямбда-функций в стандарт С++, N1958 = 06-002.

Итак, если вы считаете, что ваш код выглядит уродливым, ваше намерение очистить код приведет к поражению оригинальной мотивации лямбда.

Таким образом, если вы намереваетесь использовать алгоритмы стандартной библиотеки С++, вам необходимо использовать lambda, если это необходимо, как в случае std:: map (period). Конечно, вы все еще можете переписать с помощью итеративной манеры, но это вопрос выбора и удобочитаемости, а "читаемость лежит в глазах рецензентов"