Menyortir vector
berbagai objek jenis kustom yang X
dapat diterapkan (dapat dimutasikan input) jenis ini dapat dicapai dengan menggunakan berbagai metode, terutama termasuk penggunaan algoritma perpustakaan standar seperti
Karena sebagian besar teknik, untuk mendapatkan urutan relatif X
elemen, telah diposting, saya akan mulai dengan beberapa catatan tentang "mengapa" dan "kapan" untuk menggunakan berbagai pendekatan.
Pendekatan "terbaik" akan tergantung pada berbagai faktor:
- Apakah menyortir rentang
X
objek merupakan tugas yang umum atau jarang (akankah rentang tersebut diurutkan menjadi beberapa tempat yang berbeda dalam program atau oleh pengguna perpustakaan)?
- Apakah pemilahan yang diperlukan "alami" (diharapkan) atau apakah ada beberapa cara tipe dapat dibandingkan dengan dirinya sendiri?
- Apakah kinerja masalah atau haruskah menyortir rentang
X
objek menjadi sangat mudah?
Jika menyortir rentang X
adalah tugas umum dan penyortiran yang dicapai diharapkan (yaitu X
hanya membungkus nilai fundamental tunggal) maka mungkin akan pergi untuk kelebihan operator<
karena memungkinkan menyortir tanpa fuzz (seperti melewati pembanding yang tepat dengan benar) dan berulang kali menghasilkan diharapkan hasil.
Jika menyortir adalah tugas umum atau mungkin diperlukan dalam konteks yang berbeda, tetapi ada beberapa kriteria yang dapat digunakan untuk menyortir X
objek, saya akan mencari Functors ( operator()
fungsi kelas kustom yang berlebihan ) atau pointer fungsi (yaitu satu functor / fungsi untuk pemesanan leksikal dan satu lagi untuk pemesanan alami).
Jika menyortir rentang tipe X
jarang atau tidak mungkin dalam konteks lain saya cenderung menggunakan lambdas daripada mengacaukan namespace dengan lebih banyak fungsi atau tipe.
Ini terutama benar jika penyortiran tidak "jelas" atau "alami" dalam beberapa cara. Anda dapat dengan mudah mendapatkan logika di balik pemesanan ketika melihat lambda yang diterapkan di tempat sedangkan operator<
buram pada pandangan pertama dan Anda harus melihat definisi untuk tahu apa logika pemesanan akan diterapkan.
Namun perlu dicatat, bahwa operator<
definisi tunggal adalah titik kegagalan tunggal sedangkan banyak lambas adalah titik kegagalan ganda dan memerlukan perhatian lebih.
Jika definisi operator<
tidak tersedia di mana penyortiran dilakukan / template penyortiran dikompilasi, kompiler mungkin dipaksa untuk membuat panggilan fungsi ketika membandingkan objek, alih-alih menguraikan logika pemesanan yang mungkin merupakan kelemahan parah (setidaknya ketika optimisasi waktu taut / pembuatan kode tidak diterapkan).
Cara untuk mencapai keterbandingan class X
untuk menggunakan algoritma pengurutan perpustakaan standar
Biarkan std::vector<X> vec_X;
danstd::vector<Y> vec_Y;
1. Kelebihan T::operator<(T)
atau operator<(T, T)
dan gunakan templat pustaka standar yang tidak mengharapkan fungsi perbandingan.
Salah satu anggota kelebihan beban operator<
:
struct X {
int i{};
bool operator<(X const &r) const { return i < r.i; }
};
// ...
std::sort(vec_X.begin(), vec_X.end());
atau gratis operator<
:
struct Y {
int j{};
};
bool operator<(Y const &l, Y const &r) { return l.j < r.j; }
// ...
std::sort(vec_Y.begin(), vec_Y.end());
2. Gunakan pointer fungsi dengan fungsi perbandingan khusus sebagai parameter fungsi penyortiran.
struct X {
int i{};
};
bool X_less(X const &l, X const &r) { return l.i < r.i; }
// ...
std::sort(vec_X.begin(), vec_X.end(), &X_less);
3. Buat bool operator()(T, T)
kelebihan untuk jenis kustom yang dapat dilewatkan sebagai fungsi perbandingan.
struct X {
int i{};
int j{};
};
struct less_X_i
{
bool operator()(X const &l, X const &r) const { return l.i < r.i; }
};
struct less_X_j
{
bool operator()(X const &l, X const &r) const { return l.j < r.j; }
};
// sort by i
std::sort(vec_X.begin(), vec_X.end(), less_X_i{});
// or sort by j
std::sort(vec_X.begin(), vec_X.end(), less_X_j{});
Definisi objek fungsi tersebut dapat ditulis sedikit lebih umum menggunakan C ++ 11 dan templat:
struct less_i
{
template<class T, class U>
bool operator()(T&& l, U&& r) const { return std::forward<T>(l).i < std::forward<U>(r).i; }
};
yang dapat digunakan untuk mengurutkan jenis apa pun dengan anggota i
pendukung <
.
4. Lewati penutupan anonymus (lambda) sebagai parameter perbandingan ke fungsi penyortiran.
struct X {
int i{}, j{};
};
std::sort(vec_X.begin(), vec_X.end(), [](X const &l, X const &r) { return l.i < r.i; });
Di mana C ++ 14 memungkinkan ekspresi lambda yang lebih umum:
std::sort(a.begin(), a.end(), [](auto && l, auto && r) { return l.i < r.i; });
yang bisa dibungkus makro
#define COMPARATOR(code) [](auto && l, auto && r) -> bool { return code ; }
membuat pembuatan pembanding biasa cukup lancar:
// sort by i
std::sort(v.begin(), v.end(), COMPARATOR(l.i < r.i));
// sort by j
std::sort(v.begin(), v.end(), COMPARATOR(l.j < r.j));