Reputation: 31
I have the program that has two vectors of names and ages. It sorts the names vector and keeps the age vector in the correct order to match the sorted name vector. Now, I want to make a function from existing code, but I have some issues.
Existing code:
#include <iostream>
#include <vector>
#include <string>
#include <algorithm>
#include <iomanip>
using namespace std;
int main() {
vector<string> names {"One", "Two", "Three", "Four", "Five"};
vector<unsigned int> ages { 1, 2, 3, 4, 5};
const vector<string> namesCopy = names;
sort(begin(names), end(names));
decltype(ages) sortedAges(ages.size());
for(int i = 0; i < namesCopy.size(); ++i) {
const auto iter = lower_bound(begin(names), end(names), namesCopy[i]);
const auto pos = iter - begin(names);
sortedAges[pos] = ages[i];
}
for(int i = 0 ; i < names.size() ; ++i)
cout << setw(10) << names[i] << setw(4) << sortedAges[i] << '\n' ;
}
Function:
#include <iostream>
#include <vector>
#include <string>
#include <algorithm>
#include <iomanip>
using namespace std;
int test(vector<string> testNames, vector<string> testNamesCopy, vector<unsigned int> testAges, vector<unsigned int> testSortedAges) {
for(int i = 0; i < testNamesCopy.size(); ++i) {
const auto iter = lower_bound(begin(testNames), end(testNames), testNamesCopy[i]);
const auto pos = iter - begin(testNames);
return testSortedAges[pos] = testAges[i];
}
}
int main() {
vector<string> names {"One", "Two", "Three", "Four", "Five"};
vector<unsigned int> ages { 1, 2, 3, 4, 5};
const auto namesCopy = names;
sort(begin(names), end(names));
decltype(ages) sortedAges(ages.size());
for(int i = 0 ; i < names.size() ; ++i)
cout << setw(10) << names[i] << setw(4) << test(names, namesCopy, ages, sortedAges) << '\n' ;
}
Upvotes: 2
Views: 181
Reputation: 118097
vector<string> names {"One", "Two", "Three", "Four", "Five"}; vector<unsigned int> ages { 1, 2, 3, 4, 5};
names
and ages
seem connected in such a way that it'd be best to group them together in a class. We can use a simple struct
which, by default, gives you direct access to its members, just like you have access to all the names and ages in your current solution. You can start with this:
struct person { // ... or animal, or thing. Give it a meaningful name.
std::string name{};
unsigned age{};
};
Now you can create a std::vector<person>
instead of having two unconnected vectors, which makes sorting and general handling of the data a bit of a hassle.
With the above, sorting and printing etc. becomes more straight forward. I've used lambdas to create the sorting functions in the example:
#include <algorithm>
#include <iostream>
#include <string>
#include <vector>
#include <tuple> // std::tie
#include <iomanip>
struct person {
std::string name{};
unsigned age{};
};
// print one "person"
std::ostream& operator<<(std::ostream& os, const person& p) {
return os << std::setw(10) << p.name << std::setw(4) << p.age;
}
int main() {
// one vector with all the persons
std::vector<person> persons{
{"One", 1},
{"Two", 2},
{"Three", 3},
{"Four", 4},
{"Five", 5}
};
// sort on name first, age second (if names are equal) - ascending order
std::sort(persons.begin(), persons.end(), [](const person& a, const person& b) {
return std::tie(a.name, a.age) < std::tie(b.name, b.age);
});
// print the current order:
for(const auto& p : persons) std::cout << p << "\n";
std::cout << "--\n";
// sort on age first, name second (if ages are equal) - ascending order
std::sort(persons.begin(), persons.end(), [](const person& a, const person& b) {
return std::tie(a.age, a.name) < std::tie(b.age, b.name);
});
// print the current order:
for(const auto& p : persons) std::cout << p << "\n";
}
Upvotes: 0
Reputation: 2070
I think you are approaching this the wrong way. Having 2 vector that you sort but have to keep in the same order is error prone. Instead you should use a vector of pair.
std::vector<std::pair<std::string, int>> idendityVec;
Then you can sort by the name (the first element of the pair) by doing
std::sort(idendityVec.begin(), idendityVec.end());
If you want to sort by age, you can declare your own comparaison function and use it in the sort :
bool lesserAge(const pair<std::string,int> &a,
const pair<std::string,int> &b)
{
return (a.second < b.second);
}
std::sort(idendityVec.begin(), idendityVec.end(), lesserAge);
Which gives you something like this :
#include <iostream>
#include <vector>
#include <algorithm>
#include <utility>
bool lesserAge(const std::pair<std::string, int> &a,
const std::pair<std::string, int> &b)
{
return (a.second < b.second);
}
int main()
{
std::vector<std::pair<std::string, int>> idendityVec = {std::make_pair("three", 3), std::make_pair("four", 4), std::make_pair("two", 2), std::make_pair("one", 1)};
for (auto v : idendityVec)
{
std::cout << "Name=" << v.first << ", age=" << v.second << std::endl;
}
// Sort by age i.e. second element
std::sort(idendityVec.begin(), idendityVec.end(), lesserAge);
for (auto v : idendityVec)
{
std::cout << "Name=" << v.first << ", age=" << v.second << std::endl;
}
//Sort by name i.e first element
std::sort(idendityVec.begin(), idendityVec.end());
for (auto v : idendityVec)
{
std::cout << "Name=" << v.first << ", age=" << v.second << std::endl;
}
}
Upvotes: 2