I have some data which I need to print, for simplicity lets say it is a container (vector) of people which have some parameters. In different parts of my program, I need to print all of them sorted by different parameter. My question are
1.) which container to choose? (personally I chose vector).
2.) What approach is better, sort whole vector every time or it is better to make a copy of that vector and save it sorted? In my solution I sorted the same vector every time, but maybe it is not a correct approach with huge vectors because of speed.
class Person
{
private:
std::string name;
std::string surname;
int age;
public:
Person(std::string name, std::string surname, int age) : name{ name }, surname{ surname }, age{ age } {};
void print() { std::cout << name << " " << surname << " " << age << std::endl; };
static bool sortName(Person const &A, Person const &B) { return A.name < B.name; };
static bool sortSurname(Person const &A, Person const &B) { return A.surname < B.surname; };
static bool sortAge(Person const &A, Person const &B) { return A.age < B.age; };
};
main:
int main()
{
std::vector<Person> persons;
Person person1("John", "Smith", 30);
Person person2("Mark", "Cooper", 28);
Person person3("George", "Orwell", 19);
persons.push_back(person1);
persons.push_back(person2);
persons.push_back(person3);
std::sort(persons.begin(), persons.end(), Person::sortSurname);
for (int i = 0; i < persons.size(); ++i)
{
persons[i].print();
}
// do some other stuff here ... and then ...
std::sort(persons.begin(), persons.end(), Person::sortName);
for (int i = 0; i < persons.size(); ++i)
{
persons[i].print();
}
// do some other stuff here ... and then ...
std::sort(persons.begin(), persons.end(), Person::sortAge);
for (int i = 0; i < persons.size(); ++i)
{
persons[i].print();
}
return 0;
}
boost::multi_index_container
allows you to define a container of any type with any number of different indexes, or views.
The container keeps the indexes up to date automatically upon insertion and removal.
It's a massive template library which takes a little time to get used to, but the documentation is good, with plenty of examples.
Here's an implementation expressed this way:
#include <iostream>
#include <string>
#include <boost/multi_index_container.hpp>
#include <boost/multi_index/ordered_index.hpp>
#include <boost/multi_index/mem_fun.hpp>
class Person {
private:
std::string name;
std::string surname;
int age;
public:
Person(std::string name, std::string surname, int age) : name{name}, surname{surname}, age{age} {};
auto get_name() const -> const std::string& { return name; }
auto get_surname() const -> const std::string& { return surname; }
auto get_age() const -> int { return age; }
void print() const { std::cout << name << " " << surname << " " << age << std::endl; };
};
namespace bmi = boost::multi_index;
struct by_name {};
struct by_surname {};
struct by_age;
using PersonTable = boost::multi_index_container<Person,
bmi::indexed_by<
bmi::ordered_non_unique<bmi::tag<by_name>, bmi::const_mem_fun<Person,std::string const&,&Person::get_name>>,
bmi::ordered_non_unique<bmi::tag<by_surname>, bmi::const_mem_fun<Person,std::string const&,&Person::get_surname>>,
bmi::ordered_non_unique<bmi::tag<by_age>, bmi::const_mem_fun<Person,int,&Person::get_age>>
>
>;
int main()
{
PersonTable people;
people.insert(Person("John", "Smith", 30));
people.insert(Person("Mark", "Cooper", 28));
people.insert(Person("George", "Orwell", 19));
std::cout << "by name" << std::endl;
for (auto&& person : people.get<by_name>())
{
person.print();
}
std::cout << "\nby surname" << std::endl;
for (auto&& person : people.get<by_surname>())
{
person.print();
}
std::cout << "\nby age" << std::endl;
for (auto&& person : people.get<by_age>())
{
person.print();
}
}
expected output:
by name
George Orwell 19
John Smith 30
Mark Cooper 28
by surname
Mark Cooper 28
George Orwell 19
John Smith 30
by age
George Orwell 19
Mark Cooper 28
John Smith 30
documentation here: http://www.boost.org/doc/libs/1_64_0/libs/multi_index/doc/index.html
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With