在C ++中如何计算容器内的项目重复次数?
问题如下: 我有一个上面有很多项目的向量,我怎么知道每个元素的重复次数?
我已经看到了解决方案,您必须使用该值创建另一个向量(我们将其称为countVector),然后重复该循环,然后遍历向量,检查是否已将值添加到countVector中(如果已添加值),然后继续将重复次数增加1,但如果没有,则添加新值并将重复次数设置为1。
公平地说,此实现是一个过大的杀伤力,需要两个循环,一个循环经过item向量,另一个循环检查值是否已添加。
有没有更有效的方法?
答案 0 :(得分:0)
是的,有一种更有效的方式来执行此类任务,方法是使用地图,更确切地说是std :: map。
进行计数的算法是:
map<dataDesired, int> itemRepetitions
创建地图假设我们有一个vector<string> called items;
要计算每个项目的重复次数,我们只需要执行以下操作
std::vector<std::string> items { "ja", "an", "di", "ja", "ja", "an", "di", "be" };
std::map<std::string, int> itemsCount;
for (std::string item : items)
{
++itemsCount[item];
}
//print the map
for (auto item : itemsCount)
std::cout << "Value: " << item.first << " repetitions: " << item.second << std::endl;
输出:
Value: an repetitions: 2
Value: be repetitions: 1
Value: di repetitions: 2
Value: ja repetitions: 3
如果您希望它更“通用/全局”,则可以像往常一样创建一个模板函数来对任何类型的向量上的元素进行计数
template <class datatype>
std::map<datatype, int> count_elements_in(std::vector<datatype> items)
{
std::map<datatype, int> itemsCount;
for (datatype item : items)
++itemsCount[item];
return itemsCount;
}
此函数返回接收到的类型的映射,该映射中作为参数传递的向量中的值重复,该向量可以是任何类型。试试吧:
std::vector<std::string> itemsStr{ "ja", "an", "di", "ja", "ja", "an", "di", "be" };
std::vector<int> itemsInt{ 1, 2, 8, 4 , 1, 1, 2, 3, 3, 3 };
std::vector<double> itemsDouble{ 1.2, 2.1, 8.3, 4 , 1.2, 1.2, 2.1, 3.6, 3.6, 3.6 };
std::map<std::string, int> itemsCountStr = count_elements_in(itemsStr);
std::map<int, int> itemsCountInt = count_elements_in(itemsInt);
std::map<double, int> itemsCountDouble = count_elements_in(itemsDouble);
如果我们打印itemsCounts,我们将获得以下输出:
strings count:
Value: an repetitions: 2
Value: be repetitions: 1
Value: di repetitions: 2
Value: ja repetitions: 3
ints count:
Value: 1 repetitions: 3
Value: 2 repetitions: 2
Value: 3 repetitions: 3
Value: 4 repetitions: 1
Value: 8 repetitions: 1
floats count:
Value: 1.2 repetitions: 3
Value: 2.1 repetitions: 2
Value: 3.6 repetitions: 3
Value: 4 repetitions: 1
Value: 8.3 repetitions: 1
我们可以知道每个项目在给定容器(如矢量)中重复了多少次。
我提出了这个问题并回答,因为我注意到在与他的任务类型有关的大多数帖子中,人们倾向于使用之前解释的双循环算法,而不是使用C ++语言的功能,我知道这可能不是是执行此任务的最有效方法,但比双循环算法更优化。
答案 1 :(得分:0)
使用无序映射对查找更有效。对于无序地图,查找仅花费O(1)
#include <iostream>
#include <string>
#include <vector>
#include <unordered_map>
int main()
{
std::vector<std::string> names { "one", "two", "two", "three", "three", "three"};
std::unordered_map<std::string, int> names_map;
for (const std::string& name : names)
{
++names_map[name];
}
for (auto name : names_map)
{
std::cout << "Value: " << name.first << " repetitions: " << name.second << std::endl;
}
}