如何统计unordered_set中整数出现的频率?

问题描述 投票:0回答:3

一个可能看起来微不足道的问题,但我想知道在将包含重复整数的数组转换为

unordered_set
后,是否有一种方法可以获得唯一的整数计数。为了清楚起见,我从一些数组开始,将其变成一个
unordered_set
,突然间,
unordered_set
只包含唯一的整数,而我只是在
unordered_set
中整数的重复数之后。
这有可能吗? (类似于
unordered_set.count(index)

c++ hashmap unordered-set
3个回答
0
投票

一个可能看起来微不足道的问题,但我想知道在将包含重复整数的数组转换为 unordered_set 后,是否有一种方法可以获得唯一的整数计数。

如果容器是连续的,例如数组,那么我相信您可以在进行一些迭代器数学运算后使用

ptrdiff_t
来对它们进行计数。不过,我不确定不连续的容器。

既然你从数组开始:

  1. 在数组上调用
    unique
  2. unique
    返回
    iter.end()
  3. 使用
    ptrdiff_t count
    iter.begin()
     计算 
    iter.end()

请记住,步骤 3 中的计算需要针对

sizeof
和元素进行调整。

但套用 Beta 的话,有些容器适合这样做,而另一些容器则不适合。如果您有一个无序的集合(或地图或树),那么信息将不容易获得。


0
投票

根据你对user2357112问题的回答我会写一个解决方案。 因此,我们假设我们将使用一个向量而不是 unordered_set,并且我们的向量具有如下值:

{1, 1, 1, 3, 4, 1, 1, 4, 4, 5, 5};

所以,我们想要获取特定值在向量中出现的次数(我认为是在不同的向量中),对吧?在这种特定情况下,结果将是:1 出现 5 次,3 出现 1 次,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 属性反对向量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

0
投票

我假设您正在尝试获取唯一值及其出现次数的列表。如果是这样的话,那么

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

© www.soinside.com 2019 - 2024. All rights reserved.