Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

C++ Grouping repetitions within Vector

I've got a file structured like this:

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

Each piece of information is being stored like so:

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

I've stored this information in a Vector

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

A given personid can come up numerous times within the file. What I want to do is iterate through the vector and group the repetitions into a single class object per personid, my goal is that I want sum the data for each particular object such that the output for the file above would be:

123456 : 7
235334 : 0

What would be an elegant way to approach this?

Thanks

like image 218
Courtney White Avatar asked Sep 12 '17 07:09

Courtney White


1 Answers

The following code uses an std::unordered_map as suggested by the comments already. It will read your file line by line.
The code assumes that the person's id is of type int, the code of type std::string and the data of type int.

It inserts every Person (here as example a struct) into the map. If a person's id is already there it will sum up the data. That means that this solution doesn't use a temporary std::vector but only the std::unordered_map.

See live example with your data on ideone.com.

Code:

#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;
}

Output:

235334 : 0
123456 : 7
like image 56
Andre Kampling Avatar answered Sep 30 '22 18:09

Andre Kampling