Есть ли способ найти количество ключей в мультикарте?

size multimap сообщает о количестве содержащихся в нем значений. Меня интересует количество ключей, которые он содержит. Например, учитывая multimap<int, double> foo, я хотел бы сделать это:

const auto keyCount = ???

Один из способов получить это — использовать цикл for для инициализированного нулем keyCount:

for(auto it = cbegin(foo); foo != cend(foo); it = foo.upper_bound(foo->first)) ++keyCount;

Однако это не позволяет мне выполнять встроенную операцию. Поэтому я не могу инициализировать const auto keyCount.

Решением может быть лямбда или функция, которая оборачивает этот for-цикл, например:

template <typename Key, typename Value>
size_t getKeyCount(const multimap<Key, Value>& arg) {
    size_t result = 0U;

    for(auto it = cbegin(foo); foo != cend(foo); it = foo.upper_bound(foo->first)) ++result;
    return result;
}

Но я надеялся на что-то предусмотренное стандартом. Существует ли такая вещь?


person Jonathan Mee    schedule 20.12.2017    source источник
comment
Возможно, std::multimap — не лучшая структура данных для вас. Например, std::map<key,std::vector<value>> может работать лучше.   -  person Slava    schedule 20.12.2017
comment
как насчет const auto keyCount = std::accumulate(..., который оборачивает цикл for?   -  person 463035818_is_not_a_number    schedule 20.12.2017
comment
@Slava Это страдает от проблемы vector из vectors: stackoverflow.com/q/38244435/2642059 (хотя это все еще может быть мой лучший вариант, я все еще хотел бы получить ответ на вопрос.)   -  person Jonathan Mee    schedule 20.12.2017
comment
@tobi303 Сомневаюсь, что std::accumulate() может перепрыгнуть через уникальные ключи   -  person Slava    schedule 20.12.2017
comment
@ tobi303 tobi303 Я собирался наброситься на то, что это потребует от меня пройти через все элементы в multimap, но, когда я думаю об этом, я почти уверен, что upper_bound делает именно это. Я полагаю, по вашему мнению, мы, вероятно, могли бы сделать это, используя count_if или for_each :( Я предполагаю, что это будет такой же хороший ответ, как я собираюсь получить, если вы наберете, я соглашусь.   -  person Jonathan Mee    schedule 20.12.2017
comment
@Слава, я... не думаю, что upper_bound прыгает по клавишам, не так ли?   -  person Jonathan Mee    schedule 20.12.2017
comment
@Слава Оп, нет, отмените бинарный поиск: en. cppreference.com/w/cpp/container/multimap/   -  person Jonathan Mee    schedule 20.12.2017
comment
это было просто слепое предположение. Если я найду время позже, я напишу ответ, но мое время компиляции довольно короткое: P   -  person 463035818_is_not_a_number    schedule 20.12.2017


Ответы (3)


Нет, в стандарте нет встроенных средств для этого. Учтите, что ваша функция подсчета работает, потому что мультикарта сортируется внутри. Типичные реализации, такие как libstdc++, используют красно-черные деревья для внутреннего представления. Вам нужно будет пройтись по дереву, чтобы подсчитать все (уникальные) ключи. Это неизбежно.

person user9124890    schedule 21.12.2017

1st, multimap не содержит ключ считать наивно. Итак, ваш вопрос о том, как использовать что-то из библиотеки алгоритмов, чтобы найти количество . 2 ограничения, которые вы установили, исключают все в библиотеке:

  1. Должен использоваться как встроенный, поэтому должен быть возвращен счетчик, а не итератор.
  2. Должен работать как минимум так же хорошо, как upper_bound, используемый в лямбда-выражении, которое имеет временную сложность: O(log n)

1 оставляет нам: count, count_if, for_each, а также большинство алгоритмов в числовая библиотека

2 исключает рассмотрение всех из них, поскольку каждый из них имеет временную сложность: O(n)

Таким образом, ваш getKeyCount предпочтительнее любого другого стандартного варианта.


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

person Jonathan Mee    schedule 21.12.2017

Если вы только создаете мультикарту и вставляете в нее значения, вы можете сохранить сопутствующую карту для записи различных типов ключей. Этот размер этой карты даст вам количество ключей.

person sanjivgupta    schedule 20.09.2018
comment
Вероятно, это должен был быть комментарий :( См. Также проблемы, представленные во второй половине этого ответа: stackoverflow.com/a/47928082/ 2642059 - person Jonathan Mee; 20.09.2018