【问题标题】:C++ Grouping repetitions within VectorVector中的C ++分组重复
【发布时间】:2017-09-12 07:27:28
【问题描述】:

我有一个结构如下的文件:

A 123456 0
G 123456 5
A 235334 0
B 123456 2

每条信息都是这样存储的:

temp.code >> temp.personid >> temp.data

我已将此信息存储在 Vector 中

 ifstream fin("test.txt");
 vector<TestClass> test;
 TestClass temp;
 string line;
 while (getline(fin, line)) {//.. test.push_back(temp);}

给定的personid 可以在文件中多次出现。 我想要做的是遍历向量并将重复分组到每个personid的单个类对象中,我的目标是我想要对每个特定对象的数据求和,以便上面文件的输出应该是:

123456 : 7
235334 : 0

解决这个问题的优雅方法是什么?

谢谢

【问题讨论】:

  • a mappersonid 为键,累积 data 为数据怎么样?
  • 可以使用map,key为personid的类型,value为data的类型。
  • 在这里多地图不是更好的方法吗?

标签: c++ vector grouping repeat


【解决方案1】:

按照 cmets 的建议,以下代码使用 std::unordered_map。它将逐行读取您的文件。
代码假设人的id为int类型,代码为std::string类型,数据为int类型。

它将每个Person(这里以结构为例)插入到地图中。如果一个人的 id 已经存在,它将汇总数据。这意味着此解决方案不使用临时的std::vector,而只使用std::unordered_map

See live example with your data on ideone.com.

代码:

#include <iostream>
#include <sstream>
#include <fstream>
#include <string>
#include <unordered_map>

struct Person
{
   std::string code;
   int         data;
};

typedef std::unordered_map<int, Person> PersonMap;

int main()
{
   std::ifstream fin("test.txt");

   PersonMap persons;

   /* line by line reading */
   for (std::string line; std::getline(fin, line); )
   {
      std::istringstream iss(line);

      int    personId;
      Person personData;

      /* parse line as std::string, int, int */
      iss >> personData.code >> personId >> personData.data;

      /* insert into map and save result */
      std::pair<PersonMap::iterator, bool> insertResult =
         persons.insert(std::pair<int, Person>(personId, personData));

      /* if personId is already there */
      if (!insertResult.second)
      {
         insertResult.first->second.data += personData.data;
      }
   }

   /* output whole map */
   for(auto const &person : persons)
   {
      std::cout << person.first << " : " << person.second.data << "\n";
   }
   std::cout << std::flush;
}

输出:

235334 : 0
123456 : 7

【讨论】:

    【解决方案2】:

    使用Unordered map。在平均情况下,无序映射中的查找时间是常数O(1)。我使用向量作为示例数据,您可以从文件而不是向量中加载数据。

    #include <bits/stdc++.h>
    using namespace std;
    
    int main() {
        unordered_map<string, int>m;
        unordered_map<string, int>::iterator itr;    // Iterator to iterate unordered map
        vector<pair<string, int> >person_details;    // pair of vector to represent sample data, you can load data from file instead
        person_details.push_back(make_pair("123456",0));
        person_details.push_back(make_pair("123456",5));
        person_details.push_back(make_pair("235334",0));
        person_details.push_back(make_pair("123456",2));
        for(int i=0;i<person_details.size();i++)
        {
            if(m.find(person_details[i].first) == m.end() )                // If personId is not present in map, insert it
                m[person_details[i].first]=person_details[i].second;
            else m[person_details[i].first]+=person_details[i].second;        // If personId is present in map, increment it.
        }
        for(itr=m.begin();itr!=m.end();itr++)          
            cout<<itr->first<<" "<<itr->second<<endl;       // Displaying personId with occurance
        return 0;
    }
    
    Output:
    235334 0
    123456 7
    

    注意:您可以使用Map 来获得恒定的O(LogN) 时间,其中N 是容器的大小。

    【讨论】:

    • The complexity of lookup for std::unordered_map is O(1) (constant) in the average case, and O(N) (linear) in the worst case. 取自这里:stackoverflow.com/questions/16068151/…
    • 请记住,O(1) 等于更快的执行。有时迭代一个小向量会更快,即使它是线性搜索
    • @AndreKampling 谢谢,我已经更新了答案。 Worst case only occurs in case of too many hash collisions.
    猜你喜欢
    • 1970-01-01
    • 2012-11-30
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-01-25
    • 1970-01-01
    • 2021-11-18
    相关资源
    最近更新 更多