Hovik Ohanian
Hovik Ohanian

Reputation: 11

How can I use one function to sort by different variables in a struct

In my program, I have this struct:

struct Record {
string ID;
string name;
int quantity;
double price; 
};

I also have a function that is supposed to bubble sort an array of pointers to Record that looks like this:

void printAscending(Record* pitemList[50], int arraySize) {
  int Swap;
  Record* Temp;
  do{
    Swap = 0;
    for(int i = 0; i < (arraySize - 1); i++) {
      if ((pitemList[i] -> quantity) > (pitemList[i + 1] -> quantity)){
        Temp = pitemList[i];
        pitemList[i] = pitemList[i + 1];
        pitemList[i + 1] = Temp;
        Swap = 1;
      }
    }
  } while (Swap != 0);
}

There are four different variables in struct and I have to ask a user to pick one to sort by. I can't create four different functions for each variable, and I also can't copy and paste the same bubble sort code four times for each variable. Is there any way to create one function with one block of bubble sort code that can sort by four different variables?

Upvotes: 1

Views: 486

Answers (3)

max66
max66

Reputation: 66230

Not sure I understand what you want, but to generalize your code to use a different member of the records as a comparator, I suppose you can pass pointers to members as template parameters.

You've tagged your question as , so you can use auto for template parameters, so:

template <auto Record::* rMember>
void printAscending (Record* pitemList[50], int arraySize)
 {
   bool Swap;

   do
    {
      Swap = false;

      for (int i = 0; i < (arraySize - 1); i++)
       {
         if ( pitemList[i]->*rMember > pitemList[i + 1]->*rMember )
          { 
            std::swap(pitemList[i], pitemList[i+1]);

            Swap = true;
          }
       }
    }
   while ( true == Swap );
 }

You can call it as follows:

printAscending<&Record::quantity>(itemList, sizeItemList);

Upvotes: 4

golobitch
golobitch

Reputation: 1334

I am writing this from the top of my head but I think that this is the step in the right way.

You would need to have few functions like this:

bool compareByQuantity(const Record &a, const Record &b) {
    return a.quantity < b.quantity;
}

You would need to implement this for every property. And then, to sort this, you can provide third argument to sort method ... third argument is function. like this

std::sort(records.begin(), records.end(), compareByQuantity);

Hope this gets you on the right track

Link to sort documentation: https://en.cppreference.com/w/cpp/algorithm/sort

As pointed out by @Ted Klein Bergman you can also use a lambda directly like this

std::sort(records.begin(), records.end(), [](const Record &a, const Record &b){ return a.quantity < b.quantity }); 

Upvotes: 0

Jack Lilhammers
Jack Lilhammers

Reputation: 1247

I think it would be better to use std::sort, which lets you write just your compare functions and takes care of the sorting. You could use these:

#include <algorithm>

bool compareIDs(const Record *r1, const Record *r2) { return r1->ID < r2->ID; }
bool compareNames(const Record *r1, const Record *r2) { return r1->name < r2->name; }
bool compareQuantities(const Record *r1, const Record *r2) { return r1->quantity < r2->quantity; }
bool comparePrices(const Record *r1, const Record *r2) { return r1->price < r2->price; }

// And call sort like this: std::sort(array1, array2, compareIDs);

References:
https://en.cppreference.com/w/cpp/algorithm/sort
https://en.cppreference.com/w/cpp/named_req/Compare

Upvotes: 0

Related Questions