Sorting values C++ map data structure with many values for a key - c++

This is the format of a line my input file:
Population|City|State|ListOfHighways ==>
6|Oklahoma City|Oklahoma|I-35;I-44;I-40
6|Boston|Massachusetts|I-90;I-93
8|Columbus|Ohio|I-70;I-71
I need to create an output file with this following format:
Population
(newline)
City, State
Interstates: Comma-separated list of interstates, sorted by interstate number ascending
(newline)
==> Example:
6
Boston, Massachusetts
Interstates: I-90, I-93
Oklahoma City, Oklahoma
Interstates: I-35, I-40, I-44
8
Columbus, Ohio
Interstates: I-70, I-71
Here, the states having the same population should be grouped together and they have to be sorted alphabetically by state first and then by cities. I was able to get the format right, but I am not able to figure out which data structure to use to sort the states and then the cities.
I have map<int, vector<string> > now. key is the population and the rest is the vector. Any suggestions are welcome.

I wouldn't use a map for this at all. You should probably figure out what information you actually need for each element of the data, and create whatever data types you need to support that. E.g.
struct State
{
unsigned int Population;
std::vector<std::string> Cities;
std::vector<unsigned int> Highways;
};
You can then parse in your data, and create a std::vector<State>. Sort the vector and data as appropriate using std::sort (you can use lambdas, or create comparison functions or functors if necessary).

Related

Sorting into parallel arrays

I am trying to write a program that reads lines from a file that contains a person's name, team color, and score from a baseball league. Need to sort the input into two parallel arrays, figure out which team scored more, then print the data of the team that scored more.
I can't figure out:
How to read the file because doing getline(member, team, score) isn't working (there are no spaces). I declared variables and set to zero, but do I need to do a prototype too?
We need to sort the file into the parallel arrays using an if statement inside a while loop, so it would be: if(team == color), then it would need to put the score in one array, and the member name in the other for that color. But no idea how to write this out, since I'm not printing anything and just want to store it, and then sum the scores. Then I need to increase accumulator for each, but again not sure how to do that with multiple teams.
You'll need to write a parser for your file format, and put the data somewhere. Which leads us onto 2.
Instead of declaring multiple arrays, use a structure or similar to store data that belongs together.
-
struct Player
{
std::string name;
std::string uniformColour;
int score;
};
// Parse players from file into a std::vector<Player> or similar.
This is all very simple stuff -- I suggest you read some C++ tutorials and books aimed at beginners.

How to write to a column in a CSV file

I currently pulling data from a CSV file. The CSV file has ~ 89 columns and 2000 rows worth of data. I am getting several specific columns of data such as all of col:1,2,21,22,66,67 using a variety of getlines and loops. I then store that data into vectors within the loops. Once I have read through the entire file I now have 6 vectors full of data that I want. I make some adjustments to that data and store it back into a vector. I now want to place that new data back into those columns I took them out of without actually picking up/out the other data that I don't want. What would be the best approach for this? As I don't want to make 89 vars to hold all that other data I would much rather write over those columns in particular or something similar.
As I don't want to make 89 vars to hold all that other data I would much rather write over those columns in particular or something similar.
Instead of using 6 vectors to store column data, you can use one vector of strings to hold the data from one row. Then you update the elements at 1,2,21,22,66,67 in that vector and write it to another file.
std::vector<std::string> row; // 89 elements after read and parse a row.
Processing 500,000 rows this way should be fast enough. If it is not, try a column-oriented database, e.g. OpenTSDB

Cant interate through overflow in an unorderd map

As far as I understand both the boost:unordered_map and std::unordered_map work the same in terms of "overflow" (aka multiple things that get inserted with the same key). They store it in a "bucket" so you can then iterate over them.
For example:
key: data:
"apple" 2
"peach" 4
"apple" 3
"peach" 8
then the bucket for "apple" would contain 2 & 3, right?
Well I am having trouble acessing these things.
Here is my code:
#define ANZ 10
typedef boost::unordered_map<uint16_t, int> uuidMap_int;
using namespace std;
int main()
{
uuidMap_int uuidMap;
boost::uuids::uuid entity1;
boost::uuids::uuid entity2;
for(unsigned int i = 0;i<ANZ;i++)
uuidMap.insert(std::pair<int,int>((i<5?0:1),i));
for(unsigned int i = 0;i < uuidMap.bucket_count();i++){
for(uuidMap_int::local_iterator it = uuidMap.begin(i); it != uuidMap.end(i);++it){
std::cout<<it->first<<"|"<<it->second<<"\n";
}
}
return 0;
}
All it does is make 2 new entries to the map and filling them.
Here is what the output is supposed to look like:
0|0
0|1
0|2
.
.
.
1|5
1|6
.
.
.
1|10
But it actually looks like this
0|0
1|5
Now I dont know why this is happening. It seems like the "overflow" simply gets trashed. However I am trying to make sth simmilar to a small database, so I need a way to have a id and a bunch of data belonging to said id in a map like this.
What am I doing wrong/what other map allows me to work the way I want to?
The problem (and what #juanchopanza tries to show) is that you have to read the documentation about a class, in order to use it correctly. A map is a relationship between a key (the indexing key) and a value (the data stored). In this case, you use only two keys (namely 0 and 1) and each insert() you do to the map just refuses to insert elements on the already two key cells with the new data. The expected behaviour is the one you get (you use only two different keys, you have only two cells with data), the first entries you inserted with the only two keys you have used, each. Multimap classes allow you to have several entries with the same key, so you will get all your elements inserted properly.
But the other question that remains is why to use a map if you don't use the functionality it offers to you. The map allows you to differentiate the elements by key, so normally, you don't insert (perhaps only in multimaps, where you cannot differentiate elements by key) but put() the elements and index them by key (with the [] operator)?
Please, read thoroughly the documentation about each class.

How to get id vertex by name?

If I want to get the name by id vertex i can use this funcion: VAS(g, "name",id)
but if I want the opposite way,to get the id by the name, how can I do that?
igraph doesn't provide, on its own, a means to look up vertices by name, and for good reason - mapping from name to ID is a more challenging problem than mapping from ID to name, which is a simple array lookup operation. You could iterate through all the vertices and stop at the one that matches, but this is inefficient for large graphs (O(n) in the number of vertices). A faster way is to use some sort of associative array data structure, such as the dict in #Jasc's answer, and use the names as keys and ID's as values. (You'll need to keep this index in sync with the graph if you change it.) C, on its own, or the standard C library provide no such data structure, but there are many implementations available, for instance the GHash structure found in glib.
I found the following on the igrah website or mailinglist.
g = igraph.Graph(0, directed=True)
g.add_vertices(2)
g.vs[0]["name"] = "Bob"
g.vs[1]["name"] = "Bill"
# build a dict for all vertices to lookup ids by name
name2id = dict((v, k) for k, v in enumerate(g.vs["name"]))
# access specific vertices like this:
id_bob = name2id["Bob"]
print(g.vs[id_bob]["name"])

Sort a text file after reading it?

I have a text file that holds values like this:
30 Text
21 Text
12 Text
1 Text
3 Text
I want to read this into a 2D array to keep the number and the text identifier together. Once I've done this I want to sort this into ascending order, as the text file will be unsorted.
What is the best way to go about this in C++, should I put it in an Array? My objective is to just get the top 3 highest values from the text file. Is there a data structure that would be better suited to this or a better way to go about it? I can structure the text file anyway, its not a concrete format if that should be changed.
TIA
If you only want the top three values, the most efficient way may be to define three variables (or a three-element array), read the file line-by-line, and if a newly read line belongs in the top three, put it there.
But if you want to use containers, I'd go with a std::vector and use std::sort, assuming that the file is small enough that all the data fits in memory.
I would prefer to put them into a std::map (if you have unique keys. If not use a std::multipmap instead.) So as you insert data into the map, they will always be sorted. And if you want to get the 3 highest values, just get the first 3 items of the map.