Sort based on multiple things in C++
bool CompareData(const int& A, const int& B)
{
return (Records[A].Age < Records[B].Age) ||
((Records[A].Age == Records[B].Age) && (Records[A].Gender > Records[B].Gender)) ||
((Records[A].Age == Records[B].Age) && (Records[A].Gender == Records[B].Gender) &&
(strcmp(Records[A].Surname, Records[B].Surname) < 0));
}
This compares first by age and returns true if A should appear before B based on age.
If ages are equal, it then compares by gender, and returns true if A should appear before B based on gender (A is female and B is male).
If ages are equal and genders are equal, it then compares by surname (using strcmp
, although if you had used std::string
instead of a char array, you could have just used <
), and returns true if A should appear before B alphabetically by surname.
Is there a way to sort structs by multiple variables in C?
Use the standard function qsort
declared in the header <stdlib.h>
and write a user-defined comparison function.
Here you are.
#include <stdio.h>
#include <stdlib.h>
#define MAX_USERNAME_LENGTH 10
typedef struct
{
char username[MAX_USERNAME_LENGTH];
unsigned int rides;
unsigned int rank;
} driver;
int cmp( const void *left, const void *right )
{
const driver *a = ( const driver *)left;
const driver *b = ( const driver *)right;
if ( b->rank < a->rank )
{
return -1;
}
else if ( a->rank < b->rank )
{
return 1;
}
else
{
return ( a->rides < b->rides ) - ( b->rides < a->rides );
}
}
int main(void)
{
enum { N = 4 };
driver driver_list[N] =
{
{ "frank209", 3, 6 },
{ "john76", 7, 6 },
{ "harry99", 2, 2 },
{ "bob77", 5, 2 }
};
qsort( driver_list, N, sizeof( driver ), cmp );
for ( size_t i = 0; i < N; i++ )
{
printf( "%s, %u, %u\n",
driver_list[i].username, driver_list[i].rides, driver_list[i].rank );
}
return 0;
}
The program output is
john76, 7, 6
frank209, 3, 6
bob77, 5, 2
harry99, 2, 2
Sorting structs based on multiple conditions?
The solution is pretty simple:
std::stable_sort(entries.begin(), entries.end(),
[] (const Entry *lhs, const Entry *rhs)
{
if( lhs->count != rhs->count )
return lhs->count > rhs->count;
else
return lhs->word > rhs->word;
});
C++ Sorting an array with multiple value types using a single function
You should use C++'s standard sort function, std::sort
, declared in the <algorithm>
header with a user defined predicate.
Here is an example:
struct A{
int a1;
int a2;
string a3;
};
bool predicate(A const& lhs, A const& rhs) {
if (lhs.a1 != rhs.a1)
return lhs.a1 < rhs.a1;
if (lhs.a2 != rhs.a2)
return lhs.a2 < rhs.a2;
return lhs.a3 < rhs.a3;
}
Or as suggested by @Max you can use std::tie
:
bool predicate(A const& lhs, A const& rhs) {
return std::tie(lhs.a1, lhs.a2, lhs.a3) < std::tie(rhs.a1, rhs.a2, rhs.a3);
}
Now, pass that function to your sort
call:
std::sort(vectorA.begin(), vectorA.end(), & predicate);
Or to the sort function from your older question:
template <class T>
void sortArray(T record[]) {
bool swap = true;
while (swap) {
swap = false;
for (size_t i = 0; i < arraySize - 1; i++) {
if (predicate(record[i] ,record[i + 1])) {
T temp = record[i];
record[i] = record[i + 1];
record[i + 1] = temp;
swap = true;
}
}
}
}
How to sort multiple arrays based on one and print them out
Using the techniques used in this answer, you can create an array of indices, and sort the index array based on the criteria you're interested in. Then when referencing the data in a sorted manner, you use the index array.
#include <vector>
//...
std::vector<int> index_array;
int main()
{
for (int i = 0; i < number_of_items; ++i)
index_array.push_back(i);
//...
SelectionSort(city, size)
}
void SelectionSort(string city[], int size)
{
int i;
int j;
int indexSmallest;
string temp;
for (i = 0; i < size; ++i)
{
indexSmallest = i;
for (j = i + 1; j < size; ++j)
{
if (city[index_array[j]] < city[index_array[indexSmallest]])
{
indexSmallest = j;
}
}
temp = index_array[i];
index_array[i] = index_array[indexSmallest];
index_array[indexSmallest] = temp;
}
}
Then when accessing the arrays, use the array of indices:
for (int i = 0; i < size; ++i)
std::cout << city[index_array[i]] << "\n" << names[index_array[i]] << "\n\n";
C++ double sorting data with multiple elements
The struct you have is fine, except that you may want to add an overload of operator<
to do comparison. Here I'm doing the "compare by name, then date" comparison:
// Add this as a member function to `entry`.
bool operator<(entry const &other) const {
if (name1 < other.name1)
return true;
if (name1 > other.name1)
return false;
// otherwise name1 == other.name1
// so we now fall through to use the next comparator.
if (date < other.date)
return true;
return false;
}
[Edit: What's required is called a "strict weak ordering". If you want to get into detail about what the means, and what alternatives are possible, Dave Abrahams wrote quite a detailed post on C++ Next about it.
In the case above, we start by comparing the name1 fields of the two. If a<b
, then we immediately return true. Otherwise, we check for a>b
, and if so we return false. At that point, we've eliminated a<b
and a>b
, so we've determined that a==b
, in which case we test the dates -- if a<b
, we return true. Otherwise, we return false -- either the dates are equal, or b>a
, either of which means the test for a<b
is false. If the sort needs to sort out (no pun intended) which of those is the case, it can call the function again with the arguments swapped. The names will still be equal, so it'll still come down to the dates -- if we get false, the dates are equal. If we get true on the swapped dates, then what started as the second date is actually greater. ]
The operator<
you define in the structure defines the order that will be used by default. When/if you want you can specify another order for the sorting to use:
struct byid {
bool operator<(entry const &a, entry const &b) {
return a.id_number < b.id_number;
}
};
std::vector<entry> entries;
// sort by name, then date
std::sort(entries.begin(), entries.end());
// sort by ID
std::sort(entries.begin(), entries.end(), byid());
Order a List (C#) by many fields?
Use ThenBy
:
var orderedCustomers = Customer.OrderBy(c => c.LastName).ThenBy(c => c.FirstName)
See MSDN: http://msdn.microsoft.com/en-us/library/bb549422.aspx
Related Topics
Simple Ipc Between C++ and Python (Cross Platform)
How Can It Be Useful to Overload the "Function Call" Operator
Error: C2228: Left of '' Must Have Class/Struct/Union
Generating One Class Member Per Variadic Template Argument
Differences Between Running an Executable with Visual Studio Debugger VS Without Debugger
Type Erasure in C++: How Boost::Shared_Ptr and Boost::Function Work
How to Do a #Define Inside of Another #Define
The Difference Between Delete and Delete[] in C++
Operator << Must Take Exactly One Argument
Why Is Std::Vector::Operator[] 5 to 10 Times Faster Than Std::Vector::At()
Compile Lua Code, Store Bytecode Then Load and Execute It
How to Add Element by Element of Two Stl Vectors
Compile-Time Map and Inverse Map Values