Является ли лучший способ получить среднее значение ключа unordered_multimap?

Я ищу получить все значение одного ключа в моем unordered_multimap, который на самом деле складывает int и значение, представляющее время выполнения в наносекундах. Мне нужно получить все значение, чтобы заменить несколько ключей одним ключом со средним значением.

Я пробовал код, на самом деле это самый ценный:

std::unordered_multimap<int, std::chrono::nanoseconds> data;
std::chrono::nanoseconds average;
// *filling my map with value*
for (auto & pair : data){
  auto range = data.equal_range(pair.first);

  for_each (
    range.first,
    range.second,
    [](std::unordered_multimap<int, std::chrono::nanoseconds>::value_type& x){
      average = average + x.second;
    }
  );
  average = average / data.count(pair.first);
  data.erase(pair.first);
  data.insert({pair.first, average});
  }

Ошибка, которую я получаю error: 'average' is not captured : average = average + x.second;

1 ответ

Решение

Скорее, чем std::for_each, используйте std::accumulate.

Обратите внимание, что удаление записей из std::unordered_multimapв пределах диапазона это неопределенное поведение. Безопаснее наполнить другую емкость.

std::unordered_multimap<int, std::chrono::nanoseconds> data;
// *filling my map with value*

std::unordered_multimap<int, std::chrono::nanoseconds> new_data;
for (auto it = data.begin(); it != data.end(); ++it){
  auto range = data.equal_range(it->first);

  auto average = std::accumulate (
    range.first,
    range.second,
    std::chrono::nanoseconds{0},
    [](auto sum, auto & x){
      return sum + x.second;
    }
  ) / std::distance(range.first, range.second);

  new_data.emplace(key, average);
}
data.swap(new_data);

В качестве альтернативы, если у вас есть C++17, std::transform_reduce.

  std::transform_reduce(
    range.first,
    range.second,
    std::chrono::nanoseconds{0},
    std::plus<>{},
    [](auto & x) { return x.second; }
  )
Другие вопросы по тегам