Reputation: 365
I declared a class like this:
class myclass{
array myarr;
pair<PT3D,PT3D> mypair;
ID myid;
CString tag;
}
after fill data, i have a vector<myclass> myvec;
How can I sort this vector based on the CString value of each class?
bool SortCompare(const wchar_t* a, const wchar_t* b)
{
if (wcslen(a) == wcslen(b))
{
int k = (int)wcslen(a);
return std::wcsncmp(a, b, k);
}
else
return wcslen(a) < wcslen(b);
}
sort(myvec.begin(), myvec.end(), [h](myclass& a,
myclass& b) {
return SortCompare(a.tag, b.tag);
});
However this doesn't work properly , my desired result is a list sorted by human sort as this post.
but I don't know how to use CSortStringArray::CompareAndSwap function, how to use this code with std::sort?
How can I correct my codes?
Upvotes: 1
Views: 222
Reputation: 38092
Note CString
provides less operator so you do not have to fall back to C-API like wcsncmp
.
You are making this overcomplicated.
using C++11:
std::sort(myvec.begin(), myvec.end(), [](const myclass& a, const myclass& b) {
return a.tag < b.tag;
});
C++20 has even something simpler called projection:
std::ranges::sort(myvec, {}, &myclass::tag);
Now the issue of alphanumeric compare. This can look like this:
struct AlphanumericSplitResult {
std::string_view prefix;
std::string_view digits;
std::string_view suffix;
};
AlphanumericSplitResult alphanumericSplit(std::string_view s)
{
auto i = s.find_first_of("0123456789"sv);
i = i == std::string_view::npos ? s.size() : i;
auto j = s.find_first_not_of("0123456789"sv, i);
j = j == std::string_view::npos ? s.size() : j;
return { s.substr(0, i), s.substr(i, j - i), s.substr(j) };
}
bool asNumberLess(std::string_view l, std::string_view r)
{
return l.size() != r.size() ? l.size() < r.size() : l < r;
}
bool alphanumeric_less(std::string_view l, std::string_view r)
{
if (l.empty())
return !r.empty();
auto a = alphanumericSplit(l);
auto b = alphanumericSplit(r);
if (a.prefix != b.prefix)
return a.prefix < b.prefix;
if (a.digits != b.digits)
return asNumberLess(a.digits, b.digits);
return alphanumeric_less(a.suffix, b.suffix);
}
It passes all test I wrote: https://godbolt.org/z/hdG6fq9sa
and it is easy to feed to both algorithms.
Disclaimer: there is small bug in implementation - can you find it? Depending on requirements there are more small issues.
Upvotes: 3
Reputation: 92
In your else, you return Len(a) < Len( b) but this is not the same as Len(a) != Len(b). I would just return false in the else block since you know they aren't the same at that point.
Upvotes: -2
Reputation: 38784
std::wcsncmp
returns 0, > 0 or < 0. > 0 and < 0 are converted to true, 0 to false. Thus, compare "a" with "b" and "b" with "a" both return true. std::sort
expects a proper compare function. Perhaps you want return std::wcsncmp(a, b, k) < 0
.
Upvotes: 2