Alphabetically sort a list of objects by member in C++

11,612

Solution 1

std::list has an overloaded member function sort, that

Sorts the elements in ascending order. The order of equal elements is guaranteed to be preserved. The first version uses operator< to compare the elements, the second version uses the given comparison function comp.

To give the comparison function you can use functors:

struct sort_by_name {
  bool operator()(const Contact &a, const Contact &b)
  { return a.get_name() < b.get_name(); }
};
struct sort_by_last_name {
  bool operator()(const Contact &a, const Contact &b)
  { return a.get_last_name() < b.get_last_name(); }
};

or simpler free functions

bool cmp_by_name(const Contact &a, const Contact &b)
{ return a.get_name() < b.get_name(); }
bool cmp_by_last_name(const Contact &a, const Contact &b)
{ return a.get_last_name() < b.get_last_name(); }

and you call it either

 address_book.sort(sort_by_name());
 address_book.sort(sort_by_last_name());

or

 address_book.sort(cmp_by_name);
 address_book.sort(cmp_by_last_name);

the accessors get_name() and get_last_name() must be const.

Solution 2

Don't do your own sorting. Use std::sort(). You'll need to supply a custom comparator — something like this:

struct LastNameComp {
    bool operator()(const Contact& a, const Contact& b) const {
        return a.get_last_name() < b.get_last_name();
    }
}
⋮
std::sort(address_book.begin(), address_book.end(), LastNameComp());

If you have access to a C++11 compiler, you can do better:

std::sort(address_book.begin(), address_book.end(),
    [](const Contact& a, const Contact& b) {
        return a.get_last_name() < b.get_last_name();
    });

Solution 3

Expanding on the answers given using std::lexicographical_compare and lists internal sort.

    struct LastNameComp {
        bool operator()(const Contact& a, const Contact& b) {
            return std::lexicographical_compare(
               a.get_last_name().begin(), a.get_last_name().end(),
               b.get_last_name().begin(), b.get_last_name().end(),  
            );
        }
    };

    address_book.sort(LastNameComp());
Share:
11,612
Adrian
Author by

Adrian

Updated on June 14, 2022

Comments

  • Adrian
    Adrian about 2 years

    I'm trying to create a function to sort a list of contacts in an address book by name or last name.

     void sortList (list<Contact> & address_book){
    
     //define two iterators - first to point to the first element from the list, second to the second element
     list<Contact>::iterator it = address_book.begin();
     list<Contact>::iterator it2 = address_book.begin();
     it2++;
    
     //get the last name for the first 2 contacts
     string last_name1 = it->get_last_name();
     string last_name2 = it2->get_last_name();
    
     int i = 0;
    
     while (i < last_name1.length() && i < last_name2.length()){
    
           if (last_name1[i] < last_name2[i]){
              swap(it, it2);
              break;
           }
    
     }
    }
    

    I'm sure I'm not doing it correctly, but I'm a little bit lost with these iterators. I also know I should have another while loop to loop through all my contacts until all of them are sorted but, honestly I have no idea how to implement it.