Как посчитать уникальные целые числа в unordered_set?
Вопрос, который может показаться тривиальным, но мне интересно, есть ли способ получить количество целых чисел, сделанных уникальными после того, как я преобразовал массив, содержащий повторяющиеся целые числа, в unordered_set. Чтобы было ясно, я начинаю с некоторого массива, превращаюсь в неупорядоченный набор, и внезапно, unordered_set содержит только уникальные целые числа, и я просто после повторного числа целых чисел в unordered_set. Это вообще возможно? (что-то вроде unordered_set.count(index)?)
2 ответа
Я предполагаю, что вы пытаетесь получить список уникальных значений И количество их вхождений. Если это так, то std::map
обеспечивает самое чистое и простое решение:
//Always prefer std::vector (or at least std::array) over raw arrays if you can
std::vector<int> myInts {2,2,7,8,3,7,2,3,46,7,2,1};
std::map<int, unsigned> uniqueValues;
//Get unique values and their count
for (int val : myInts)
++uniqueValues[val];
//Output:
for (const auto & val : uniqueValues)
std::cout << val.first << " occurs " << val.second << " times." << std::endl;
В этом случае это не должно быть std::unordered_set
,
По вашему ответу на вопрос user2357112 я напишу решение. Итак, давайте предположим, что вместо unordered_set мы будем использовать вектор, а наш вектор имеет такие значения:
{1, 1, 1, 3, 4, 1, 1, 4, 4, 5, 5};
Итак, мы хотим получить числа (я думаю, в другом векторе), сколько раз конкретное значение появляется в векторе, верно? И в этом конкретном случае результат будет: 1 появляется 5 раз, 3 появляется один раз, 4 появляется 3 раза и 5 появляется 2 раза.
Чтобы сделать это, одно из возможных решений может быть таким:
- Получите уникальные записи из исходного вектора и сохраните их в другом векторе, поэтому этот вектор будет содержать: 1, 3, 4, 5
- Итерируйте по всему уникальному вектору и считайте эти элементы из исходного вектора.
- Результат печати
Код из пункта 1 может быть таким:
template <typename Type>
vector<Type> unique_entries (vector<Type> vec) {
for (auto iter = vec.begin (); iter != vec.end (); ++iter) {
auto f = find_if (iter+1, vec.end (), [&] (const Type& val) {
return *iter == val;
});
if (f != vec.end ()) {
vec.erase (remove (iter+1, vec.end (), *iter), vec.end ());
}
}
return vec;
}
Код из пункта 2 может быть таким:
template <typename Type>
struct Properties {
Type key;
long int count;
};
template <typename Type>
vector<Properties<Type>> get_properties (const vector<Type>& vec) {
vector<Properties<Type>> ret {};
auto unique_vec = unique_entries (vec);
for (const auto& uv : unique_vec) {
auto c = count (vec.begin (), vec.end (), uv); // (X)
ret.push_back ({uv, c});
}
return ret;
}
Конечно, нам не нужен класс Properties для хранения значения ключа и счетчика, вы можете вернуть только вектор типа int (с количеством элементов), но, как я уже сказал, это одно из возможных решений. Таким образом, используя unique_entries, мы получаем вектор с уникальными записями (:)), затем мы можем перебирать весь вектор vec (get_properties, используя std::count, помеченный как (X)), и объект Push_back Properties для вектора ret.
Код из пункта 3 может быть таким:
template <typename Type>
void show (const vector<Properties<Type>>& vec) {
for (const auto& v : vec) {
cout << v.key << " " << v.count << endl;
}
}
// usage below
vector<int> vec {1, 1, 1, 3, 4, 1, 1, 4, 4, 5, 5};
auto properties = get_properties (vec);
show (properties);
И результат выглядит так:
1 5
3 1
4 3
5 2
Стоит отметить, что этот пример был написан с использованием шаблонов, чтобы обеспечить гибкость выбора типа элементов в векторе. Если вы хотите хранить значения типа long, long long, short и т. Д. Вместо типа int, все, что вам нужно сделать, это изменить определение исходного вектора, например:
vector<unsigned long long> vec2 {1, 3, 2, 3, 4, 4, 4, 4, 3, 3, 2, 3, 1, 7, 2, 2, 2, 1, 6, 5};
show (get_properties (vec2));
будет производить:
1 3
3 5
2 5
4 4
7 1
6 1
5 1
который является желаемым результатом.
Еще одно замечание, вы можете сделать это и с вектором строки.
vector<string> vec_str {"Thomas", "Rick", "Martin", "Martin", "Carol", "Thomas", "Martin", "Josh", "Jacob", "Jacob", "Rick"};
show (get_properties (vec_str));
И результат:
Thomas 2
Rick 2
Martin 3
Carol 1
Josh 1
Jacob 2
Вопрос, который может показаться тривиальным, но мне интересно, есть ли способ получить количество целых чисел, сделанных уникальными после того, как я преобразовал массив, содержащий повторяющиеся целые числа, в unordered_set.
Если контейнер является смежным, как массив, то я считаю, что вы можете использовать ptrdiff_t
посчитать их после выполнения математических итераторов. Я не уверен насчет несмежных контейнеров.
Поскольку вы начинаете с массива:
- Вызов
unique
на массиве unique
возвращаетсяiter.end()
- подсчитывать
ptrdiff_t count
с помощьюiter.begin()
а такжеiter.end()
Помните, что расчет на шаге 3 необходимо скорректировать с учетом sizeof
и элемент.
Но, перефразируя бета-версию, некоторые контейнеры поддаются этому, а другие - нет. Если у вас есть неупорядоченный набор (или карта, или дерево), информация будет недоступна.