0

Is there a way to sort a struct of vectors? Given my struct looks like this

struct Data
{
    std::vector<std::string> Dates;
    std::vector<double> DateSeconds, other1, other2, other3, other4, other5;
};

And the way I sort by (lets take DateSeconds) is,

int __cdecl CompareWithDateSeconds(const void* lhs, const void* rhs)
{
    for (int i = 0; i < m_DataSize; i++) {
        const Data* a = (const Data*)lhs;
        const Data* b = (const Data*)rhs;
        double delta = a->DateSeconds[i] - b->DateSeconds[i];

        if (delta > 0)
            return (SortDirection == Ascending) ? +1 : -1;
        if (delta < 0)
            return (SortDirection == Ascending) ? -1 : +1;
    }
}

and then

qsort(&m_Data.DateSeconds[0], m_DataSize, sizeof(m_Data.DateSeconds[0]), CompareWithDateSeconds);
  • 2
    _Is there a way to sort a struct of vectors?_ Yes. It can be done with `std::sort()` and the appropriate custom predicate. – Scheff's Cat Jul 20 '21 at 07:59
  • Don't use C API for STL containers like vector. Behavior of this is undefined. [std::sort](https://en.cppreference.com/w/cpp/algorithm/sort) shell be used instead. Or if you know that elements of this vector should be unique, you can use [std::set](https://en.cppreference.com/w/cpp/container/set) instead of vector, this is Red-Black based container, which automatically sort elements inside. – Victor Gubin Jul 20 '21 at 08:00
  • Will that make the positioning of each element sorted in `DateSeconds` consistent within the other vectors? I.e. If represented in a table and `DateSeconds` is sorted, the others change too? – asjhdbashjdbasjhdbhjb Jul 20 '21 at 08:01
  • No. In this case, the data should be modeled resp. i.e. with an appropriate `struct` or `class` to bundle the values which belong together. Alternatively, you could add another `std::vector` for indices and sort this with a custom predicate which sorts these indices according to the values they address. – Scheff's Cat Jul 20 '21 at 08:03
  • @Scheff'sCat How would I do that? – asjhdbashjdbasjhdbhjb Jul 20 '21 at 08:04
  • FYI: [SO: C++ sorting and keeping track of indexes](https://stackoverflow.com/q/1577475/7478597), [SO: c++ sort keeping track of indices \[duplicate\]](https://stackoverflow.com/q/10580982/7478597) – Scheff's Cat Jul 20 '21 at 08:07
  • 1
    @VictorGubin Where specifically does UB arise when using C qsort() on a std::vector? – John Zwinck Jul 20 '21 at 08:12
  • Or possibly [sorting multiple vectors](https://stackoverflow.com/questions/44854972/sorting-multiple-vectors-in-single-sort-call-c) – Caleth Jul 20 '21 at 08:13
  • 1
    @JohnZwinck the part where they are casting `double *` to `const Data *` – Caleth Jul 20 '21 at 08:15
  • @Caleth That is just an obvious bug in the implementation and has nothing to do with VictorGubin's claim that "using a C API for STL containers like vector" is UB. – John Zwinck Jul 20 '21 at 08:16
  • Well it makes it really easy to have UB like this. `std::sort` doesn't type-erase the element type, so it can be both faster and safer – Caleth Jul 20 '21 at 08:19
  • Thanks @Scheff'sCat your suggestions got me a solution! – asjhdbashjdbasjhdbhjb Jul 20 '21 at 08:29
  • OK, I just was about to prepare an answer. This is what I got so far: [**Demo on coliru**](http://coliru.stacked-crooked.com/a/8341b607055b780f) – Scheff's Cat Jul 20 '21 at 08:31
  • @Scheff'sCat Not sure why the question is closed with that link, that wasn't even the one that helped me. It was the https://stackoverflow.com/questions/1577475/c-sorting-and-keeping-track-of-indexes so @ whoeverclosed it could you change it to this link instead. – asjhdbashjdbasjhdbhjb Jul 20 '21 at 08:45

0 Answers0