Заполнение контейнера std::map с учётом значений по умолчанию

99
26 марта 2021, 22:30

Подскажите можно ли сделать следующую задачу "в одну строчку", т.е. с помощью stl сделать более компактной/быстрой/оптимальной

есть контейнер

std::map<int, int> objects;

в котором находятся какие-то ключи в каком-то диапазоне

требуется сформировать новый контейнер на основании предыдущего в диапазоне от min до max, так чтобы недостающие значения были нулевыми

сейчас делаю так (задача - некоторые данные перевести к гистограмному виду):

// сформировать гистограмму
const int histogramSize = histBins.second - histBins.first + 1;
int* histogramData = new int[histogramSize];
memset(histogramData, 0, sizeof(int) * histogramSize);
for (const auto &it : pointsData)
{
    if ((it.first >= histBins.first) && (it.first <= histBins.second))
        histogramData[it.first - histBins.first] = it.second;
}
// сформировать выходные данные
statistics_report_t output;
for (int binIndex = histBins.first; binIndex <= histBins.second; binIndex++)
    output.insert(statistics_report_pr(binIndex, histogramData[binIndex - histBins.first]));
delete[] histogramData;

Может можно какие-то куски кода переписать более оптимально (однокомандно)? :)

Answer 1

Если обратиться к map через оператор [] к ключу, которого нет, то в map создастся узел с таким ключом и дефолтным значением (0 для int). Получается, что вообще не нужно никаких функций для расширения map, просто используйте такой синтаксис int value = objects[key]; и вам вернётся 0, если нет значения по такому ключу. Если же всё же требуется, чтобы в map присутствовал весь диапазон ключей, то достаточно скопировать оригинальную map и сделать insert по данному диапазону. insert не меняет value по ключу, который уже есть в map.

std::map<int, int> objects = { {5,2},{6,3},{7,4} };
int min = 1;
int max = 10;
std::map<int, int> newMap = objects;
for (int i = min; i <= max; i++) {
    newMap.insert({ i, 0 });
}
Answer 2

Тут наблюдается типичная проблема XY. Создавать и заполнять дополнительные контейнеры совсем необязательно, достаточно просто возвращать дефолтное значение, если элемент с требуемым ключом отсутствует в исходом контейнере.

Answer 3

Вариант №...

void
complete(std::map<int, int>& m, int min, const int max)
{   while (m[min] || (min <= max)) ++min; }
Answer 4
for (const auto &it : pointsData)
{
    if ((it.first >= histBins.first) && (it.first <= histBins.second))

Нет смысла пролистывать весь контейнер, когда нужен только фрагмент:

for (
  auto it = pointsData.lower_bound(histBins.first);
  *it != pointsData.end() && it.first <= histBins.second;
  ++it
) {
  ...
READ ALSO
Как увеличить размер QWidget за пределы Parent Widget

Как увеличить размер QWidget за пределы Parent Widget

Когда увеличиваешь размер виджета то не выходит за пределы родителя А если не даешь указатель на родителя то нормально выходит за пределы...

148
Как подключить внешнюю библиотеку в Clion

Как подключить внешнюю библиотеку в Clion

Как подключить внешнюю библиотеку в Clion?

113
boost::signals2 возможен ли асинхронный запуск?

boost::signals2 возможен ли асинхронный запуск?

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

109
Ошибка с использованием контейнера и шаблона [дубликат]

Ошибка с использованием контейнера и шаблона [дубликат]

столкнулся с ошибками в следующем коде

90