Как посчитать уникальные целые числа в 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. Получите уникальные записи из исходного вектора и сохраните их в другом векторе, поэтому этот вектор будет содержать: 1, 3, 4, 5
  2. Итерируйте по всему уникальному вектору и считайте эти элементы из исходного вектора.
  3. Результат печати

Код из пункта 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 посчитать их после выполнения математических итераторов. Я не уверен насчет несмежных контейнеров.

Поскольку вы начинаете с массива:

  1. Вызов unique на массиве
  2. unique возвращается iter.end()
  3. подсчитывать ptrdiff_t count с помощью iter.begin() а также iter.end()

Помните, что расчет на шаге 3 необходимо скорректировать с учетом sizeof и элемент.

Но, перефразируя бета-версию, некоторые контейнеры поддаются этому, а другие - нет. Если у вас есть неупорядоченный набор (или карта, или дерево), информация будет недоступна.

Другие вопросы по тегам