C++ Sort Vector of Structs: By Field with std::sort
To sort a vector of structs in C++, pass std::sort a lambda that compares the field you care about: std::sort(v.begin(), v.end(), [](const auto& a, const auto& b){ return a.field < b.field; }). The lambda tells sort which element should come first.
The Setup
Say we have a struct for people and a vector of them:
#include <iostream>
#include <vector>
#include <string>
#include <algorithm>
struct Person {
std::string name;
int age;
};
int main() {
std::vector<Person> people = {
{"Alice", 30}, {"Bob", 25}, {"Carol", 35}
};
// sorting comes next
return 0;
}
By default std::sort has no idea how to order a Person — there’s no built-in rule for “less than” on a struct. We supply that rule with a comparator.
Sort by a Single Field
A lambda comparator takes two elements and returns true if the first should come before the second:
std::sort(people.begin(), people.end(),
[](const Person& a, const Person& b) {
return a.age < b.age; // youngest first
});
for (const Person& p : people)
std::cout << p.name << " (" << p.age << ")\n";
// Bob (25), Alice (30), Carol (35)
Reading a.age < b.age as “a comes before b when a is younger” makes ascending order. To sort by name instead, just compare a.name < b.name — std::string already knows alphabetical order.
Descending Order
To reverse the order, flip the comparison operator:
std::sort(people.begin(), people.end(),
[](const Person& a, const Person& b) {
return a.age > b.age; // oldest first
});
Using > instead of < puts larger values first. That single character is the only difference between ascending and descending.
Sort by Multiple Fields
To sort by age, then break ties by name, compare the second field only when the first is equal. The clean way is std::tie, which compares fields in order:
#include <tuple>
std::sort(people.begin(), people.end(),
[](const Person& a, const Person& b) {
return std::tie(a.age, a.name) < std::tie(b.age, b.name);
});
std::tie groups the fields into a tuple, and tuples compare left to right: first by age, and only if ages match, by name. This scales to as many fields as you like without nested if statements.
Tip: Define operator< for a Natural Order
If a struct has one obvious default ordering, define operator< on it. Then plain std::sort(v.begin(), v.end()) works with no comparator:
struct Person {
std::string name;
int age;
bool operator<(const Person& other) const {
return age < other.age;
}
};
This is handy when you’ll sort the same way repeatedly, but a lambda is more flexible when you sort by different fields in different places.
Related Articles
- C++ Sort Algorithm — std::sort in full detail
- C++ Structs Explained — defining and using structs
- C++ Lambda Functions — the comparator syntax
- C++ Vector Tutorial — the container being sorted
- C++ Struct vs Class — when to use each
Take Your C++ Further
If you’re looking to go deeper with C++, the C++ Better Explained Ebook is perfect for you — whether you’re a complete beginner or looking to solidify your understanding. Just $19.