Sort One Vector Based on the Elements of Another V

2019-07-24 03:32发布

问题:

#include <algorithm>
#include <fstream>
#include <iostream>
#include <vector>
using namespace std;

const int max_applications_num = 1000;

vector<string> vector_authors;
vector<string> vector_titles;
vector<string> vector_venue;
vector<int> vector_year;
vector<string> vector_presentation;

void Tokenize(string line, vector<string> &tokens, string delimiters = "\t ") {
    string token = "";
    string OneCharString = " ";
    for (int i = 0; i < line.size(); i++)
        if (find(delimiters.begin(), delimiters.end(), line[i]) !=
            delimiters.end()) // line[i] is one of the delimiter characters
        {
            if (token != "")
                tokens.push_back(token);
            token = "";
        } else {
            OneCharString[0] = line[i];
            token += OneCharString;
        }

    if (token != "")
        tokens.push_back(token);
}

void SaveApplication(const vector<string> &tokens) {

    string authors = tokens[1];
    string title = tokens[2];
    string venue = tokens[3];
    int year = atoi(tokens[4].c_str());
    string presentation = tokens[5];

    vector_authors.push_back(authors);
    vector_titles.push_back(title);
    vector_venue.push_back(venue);
    vector_year.push_back(year);
    vector_presentation.push_back(presentation);

    // cout << "in save" << endl;
}

void remove_application(int pos) {

    vector_authors.erase(vector_authors.begin() + pos);
    vector_titles.erase(vector_titles.begin() + pos);
    vector_venue.erase(vector_venue.begin() + pos);
    vector_year.erase(vector_year.begin() + pos);
    vector_presentation.erase(vector_presentation.begin() + pos);

    // cout << "in remove" << endl;
}

void sort() {
    for (int j = 0; j <= vector_year.size() - 1; j++) {

        int temp1 = vector_year.at(j);
        int i = j - 1;
        while (i > -1 and vector_year.at(i) > temp1) {
            vector_year.at(i + 1) = vector_year.at(i);
            i = i - 1;
        }
        vector_year.at(i + 1) = temp1;
    }

    for (int j = 0; j <= vector_authors.size() - 1; j++) {
        string temp2 = vector_authors.at(j);
        int i = j - 1;
        while (i > -1 and vector_authors.at(i) > temp2) {
            vector_authors.at(i + 1) = vector_authors.at(i);
            i = i - 1;
        }
        vector_authors.at(i + 1) = temp2;
    }

    for (int j = 0; j <= vector_titles.size() - 1; j++) {
        string temp3 = vector_titles.at(j);
        int i = j - 1;
        while (i > -1 and vector_titles.at(i) > temp3) {
            vector_titles.at(i + 1) = vector_titles.at(i);
            i = i - 1;
        }
        vector_titles.at(i + 1) = temp3;
    }
    for (int j = 0; j <= vector_venue.size() - 1; j++) {
        string temp4 = vector_venue.at(j);
        int i = j - 1;
        while (i > -1 and vector_venue.at(i) > temp4) {
            vector_venue.at(i + 1) = vector_venue.at(i);
            i = i - 1;
        }
        vector_venue.at(i + 1) = temp4;
    }
    for (int j = 0; j <= vector_presentation.size() - 1; j++) {
        string temp5 = vector_presentation.at(j);
        int i = j - 1;
        while (i > -1 and vector_presentation.at(i) > temp5) {
            vector_presentation.at(i + 1) = vector_presentation.at(i);
            i = i - 1;
        }
        vector_presentation.at(i + 1) = temp5;
    }

    // cout << "in sort" << endl;
}

void print() {

    for (int i = 0; i < vector_authors.size(); i++) {
        cout << vector_authors.at(i) << "\t" << vector_titles.at(i) << "\t"
             << "\t" << vector_venue.at(i) << "\t" << vector_year.at(i) << "\t" << vector_presentation.at(i) << endl;
    }
    cout << "\n" << endl;
}

void ExecuteCommands(const char *fname) {
    ifstream inf;
    inf.open(fname);

    string line;
    while (getline(inf, line).good()) {
        vector<string> tokens;
        Tokenize(line, tokens, "\t ");
        if (tokens.size() == 0)
            continue;

        if (tokens[0].compare("save_application") == 0)
            SaveApplication(tokens);

        else if (tokens[0].compare("remove_application") == 0)
            remove_application(atoi(tokens[1].c_str()));

        else if (tokens[0].compare("sort") == 0)
            sort();

        else if (tokens[0].compare("print") == 0)
            print();
    }

    inf.close();
}

int main(int argc, char **argv) {
    if (argc != 2) {
        cout << "usage: executable.o command.txt\n";
        return 1;
    }

    ExecuteCommands(argv[1]);
    return 0;
}

So, here is my code for a lab I am doing at school. We are supposed to put certain elements in a vector, print those vectors, order them, print them again, remove a vector, print them one last time. For our sort, we need to order them based on the year of publication.

"authors_list1" "title1" "conference1"  2016    "poster"
"authors_list3" "title3" "conference2"  2010    "oral"
"authors_list2" "title2" "journal1" 2015    "none"

So, when I sort, I get this:

"authors_list1" "title1" "conference1"  2010    "none"
"authors_list2" "title2" "conference2"  2015    "oral"
"authors_list3" "title3" "journal1" 2016    "poster"

This is the expected output:

"authors_list3" "title3"    "conference2"   2010    "oral"
"authors_list2" "title2"    "journal1"  2015    "none"
"authors_list1" "title1"    "conference1"   2016    "poster"

The order of the years are correct, but the orders of everything else are not. I need my other elements to follow suit with the years. Is there any way to do that?

P.S. For this lab, we are not allowed to use classes or structs. This is all the code I have.

回答1:

You can fake a non-clumsy data structure with

vector<vector<string> > database;

Where vector<string> is a single record. To make it "manageable" I'd use some aliases, accessor functions and this enum:

enum { AUTHOR, TITLE, VENUE, YEAR, PRESENTATION };

The code becomes a lot shorter:

Live On Coliru

#include <algorithm>
#include <fstream>
#include <iostream>
#include <vector>
#include <cassert>
using namespace std;

const int max_applications_num = 1000;

enum { AUTHOR, TITLE, VENUE, YEAR, PRESENTATION };

vector<vector<string> > database;

void Tokenize(string line, vector<string> &tokens, string delimiters = "\t ") {
    string token = "";
    string OneCharString = " ";
    for (size_t i = 0; i < line.size(); i++)
        if (find(delimiters.begin(), delimiters.end(), line[i]) !=
            delimiters.end()) // line[i] is one of the delimiter characters
        {
            if (token != "")
                tokens.push_back(token);
            token = "";
        } else {
            OneCharString[0] = line[i];
            token += OneCharString;
        }

    if (token != "")
        tokens.push_back(token);
}

void SaveApplication(const vector<string> &tokens) {
    database.emplace_back(tokens.begin()+1, tokens.end());
}

void remove_application(size_t pos) {
    assert(pos < database.size());
    database.erase(database.begin()+pos);
}

int year_of(vector<string> const &record) { return stoi(record[YEAR]); }
int year_of(int i) { return year_of(database.at(i)); }

void sort() {
    for (size_t j = 0; j <= database.size() - 1; j++) {

        vector<string> tmp = database.at(j);

        int tmp_year = year_of(tmp);

        int i = j - 1;
        while (i > -1 and year_of(i) > tmp_year) {
            database.at(i + 1) = database.at(i);
            i = i - 1;
        }

        database.at(i + 1) = tmp;
    }
}

void print() {
    for (size_t i = 0; i < database.size(); i++) {
        cout 
            << database.at(i)[AUTHOR] << "\t"
            << database.at(i)[TITLE]  << "\t"
            << database.at(i)[VENUE]  << "\t"
            << database.at(i)[YEAR]   << "\t"
            << database.at(i)[PRESENTATION] 
            << endl;
    }
    cout << "\n" << endl;
}

void ExecuteCommands(const char *fname) {
    ifstream inf;
    inf.open(fname);

    string line;
    while (getline(inf, line).good()) {
        vector<string> tokens;
        Tokenize(line, tokens, "\t ");
        if (tokens.size() == 0)
            continue;

        if (tokens[0].compare("save_application") == 0)
            SaveApplication(tokens);

        else if (tokens[0].compare("remove_application") == 0)
            remove_application(atoi(tokens[1].c_str()));

        else if (tokens[0].compare("sort") == 0)
            sort();

        else if (tokens[0].compare("print") == 0)
            print();
    }

    inf.close();
}

int main(int argc, char **argv) {
    if (argc != 2) {
        cout << "usage: executable.o command.txt\n";
        return 1;
    }

    ExecuteCommands(argv[1]);
}

For the input

save_application "authors_list1"    "title1" "conference1"  2016    "poster"
save_application "authors_list3"    "title3" "conference2"  2010    "oral"
save_application "authors_list2"    "title2" "journal1" 2015    "none"
print
sort
print
remove_application 0
print

Prints

"authors_list1" "title1"    "conference1"   2016    "poster"
"authors_list3" "title3"    "conference2"   2010    "oral"
"authors_list2" "title2"    "journal1"  2015    "none"


"authors_list3" "title3"    "conference2"   2010    "oral"
"authors_list2" "title2"    "journal1"  2015    "none"
"authors_list1" "title1"    "conference1"   2016    "poster"


"authors_list2" "title2"    "journal1"  2015    "none"
"authors_list1" "title1"    "conference1"   2016    "poster"


回答2:

Why dont you use parallel vectors, and when you order the years vector, if you swap position i with position j, do it on every vector.