【问题标题】:Count item repetitions within a container [duplicate]计算容器内的项目重复次数[重复]
【发布时间】:2019-04-21 06:21:58
【问题描述】:

如何在 C++ 中计算容器内的项目重复次数?

问题是这样的: 我有一个向量,上面有很多项,我怎么知道每个元素的重复次数?

我已经看到了一些解决方案,您必须使用值和重复创建另一个向量(我们称之为 countVector),然后循环遍历向量,检查该值是否尚未添加到 countVector(如果已添加该值)继续将重复次数增加 1,但如果没有,则添加新值并将重复次数设置为 1。

说句公道话,这个实现有点矫枉过正,需要两个循环,一个遍历 items 向量,另一个检查是否添加了值。

有没有更有效的方法来做到这一点?

【问题讨论】:

    标签: c++ c++11 vector stl std


    【解决方案1】:

    是的,有一种更有效的方法来完成此类任务,即使用地图,更准确地说是 std::map。

    进行计数的算法是:

    • map<dataDesired, int> itemRepetitions创建地图
    • 遍历项目向量
    • 增加 itemRepetitions[itemInVector]

    假设我们有一个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++ 语言的特性,我知道这可能不是完成这项任务的最有效方法,但比双循环算法更优化。

    【讨论】:

      【解决方案2】:

      使用无序映射对查找更有效。查找无序地图只需 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;
          }
      }
      

      【讨论】:

      • 很高兴知道 std::map 有更好的实现,我认为 std::map 被散列但似乎我错了,谢谢提示。
      • 实际上,std::unordered_map 中的查找速度可以与O(1) 一样快。它们也可以像O(N) 一样慢。取决于数据和哈希算法。
      猜你喜欢
      • 1970-01-01
      • 2020-01-03
      • 2021-03-10
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-05-10
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多