カテゴリー【C/C++】
【C++】shared_ptrで生成したクラス配列を複数の優先順位でソートする
POSTED BY
2023-12-16
2023-12-16
普通に複数のメンバ変数・メンバ関数を持つオリジナルクラスを、std::shared_ptrでメモリ確保・初期化し、std::vector配列に格納するまでは一般的だが、それを好きな条件でその場でソートする例が意外に見つからなかったのでメモ。
C++11以降であればインラインで比較関数記述ができるラムダ式std::sortが使える。
以下の例は、時間のメンバ変数mJikan、距離のメンバ変数mDistanceと、それを出力する関数dumpを持つオリジナルクラスAを定義し、shared_ptrでこのクラスを5個生成し、順不同なmJikan、mDistanceのままvectorにまず格納している。
そしてstd::sortの第3引数に比較関数を定義する。第3引数は以下のような形式を取る。
[](auto const& c1, auto const& c2) { //ここに比較条件を記述し、 //入れ替えるならtrue、入れ替えないならfalseをreturnする });
auto const& c1,c2はそれぞれvectorに格納されている比較すべき2つのオブジェクト=格納したのはポインタshared_ptrなのでクラスAへのsharedポインタ=である。
つまりc1ー>mJikanなどと、自身のメンバ変数や関数、さらにクラス外のstd::関数やstaticクラスのメンバ関数なども好きに呼べるので複雑な比較条件のもと真ならtrueを返せばvector内の順番は入れ替わる。
ここでポイントとなるのは複数のメンバ変数を優先順位で比較したい場合。その場合はstd::tieで優先したいメンバ変数を順に列挙することで実現する。以下、最後の例がそれである。
C/C++ | shared_vector_sort.cpp | GitHub Source |
#include <iostream> #include <algorithm> #include <vector> #include <memory> #include <tuple> class A { public: int mJikan; int mDistance; A(int jikan, int distance) { mJikan = jikan; mDistance = distance; } ~A(void) { } void dump(void) { std::cout << "mJikan=" << mJikan << ", mDistance=" << mDistance << std::endl; } }; int main(void) { std::shared_ptr<A> a1 = std::make_shared<A>(10, 2); std::shared_ptr<A> a2 = std::make_shared<A>(4, 0); std::shared_ptr<A> a3 = std::make_shared<A>(7, 6); std::shared_ptr<A> a4 = std::make_shared<A>(7, 3); std::shared_ptr<A> a5 = std::make_shared<A>(6, 1); std::vector<std::shared_ptr<A>> va = std::vector<std::shared_ptr<A>>(); va.push_back(a1); va.push_back(a2); va.push_back(a3); va.push_back(a4); va.push_back(a5); //mJikanの昇順でソートする場合 std::sort(va.begin(), va.end(), [](auto const& c1, auto const& c2) { return c1->mJikan < c2->mJikan; }); std::cout << "Sorted by A->mJikan" << std::endl; std::for_each(va.begin(), va.end(), [](auto const& c) { c->dump(); }); //mDistanceの昇順でソートする場合 std::sort(va.begin(), va.end(), [](auto const& c1, auto const& c2) { return c1->mDistance < c2->mDistance; }); std::cout << "Sorted by A->mDistance" << std::endl; std::for_each(va.begin(), va.end(), [](auto const& c) { c->dump(); }); //mJikanの昇順でソートし、mJikanが同一ならmDistanceの昇順でソートする場合 std::sort(va.begin(), va.end(), [](auto const& c1, auto const& c2) { return std::tie(c1->mJikan, c1->mDistance) < std::tie(c2->mJikan, c2->mDistance); }); std::cout << "Sorted by A->mJikan AND A->mDistance" << std::endl; std::for_each(va.begin(), va.end(), [](auto const& c) { c->dump(); }); return 0; }
コンパイル、実行結果
g++ shared_vector_sort.cpp ./a.out Sorted by A->mJikan mJikan=4, mDistance=0 mJikan=6, mDistance=1 mJikan=7, mDistance=6 mJikan=7, mDistance=3 mJikan=10, mDistance=2 Sorted by A->mDistance mJikan=4, mDistance=0 mJikan=6, mDistance=1 mJikan=10, mDistance=2 mJikan=7, mDistance=3 mJikan=7, mDistance=6 Sorted by A->mJikan AND A->mDistance mJikan=4, mDistance=0 mJikan=6, mDistance=1 mJikan=7, mDistance=3 mJikan=7, mDistance=6 mJikan=10, mDistance=2
最後の例は、「mJikanが同一ならmDistanceの昇順」とstd::tieで指定しているので、最初の例と比較して、mDistance=3, 6がしっかり入れ替わっていることが確認できる。
Android
iPhone/iPad
Flutter
MacOS
Windows
Debian
Ubuntu
CentOS
FreeBSD
RaspberryPI
HTML/CSS
C/C++
PHP
Java
JavaScript
Node.js
Swift
Python
MatLab
Amazon/AWS
CORESERVER
Google
仮想通貨
LINE
OpenAI/ChatGPT
IBM Watson
Microsoft Azure
Xcode
VMware
MySQL
PostgreSQL
Redis
Groonga
Git/GitHub
Apache
nginx
Postfix
SendGrid
Hackintosh
Hardware
Fate/Grand Order
ウマ娘
将棋
ドラレコ
※本記事は当サイト管理人の個人的な備忘録です。本記事の参照又は付随ソースコード利用後にいかなる損害が発生しても当サイト及び管理人は一切責任を負いません。
※本記事内容の無断転載を禁じます。
※本記事内容の無断転載を禁じます。
【WEBMASTER/管理人】
自営業プログラマーです。お仕事ください!ご連絡は以下アドレスまでお願いします★
【キーワード検索】
【最近の記事】【全部の記事】
Intel Macbook2020にBootCampで入れたWindows11 Pro 23H2のBluetoothを復活させるWindowsのデスクトップ画面をそのまま配信するための下準備
WindowsでGPUの状態を確認するには(ASUS系監視ソフトの自動起動を停止する)
CORESERVER v1プランからさくらインターネットスタンダートプランへ引っ越しメモ
さくらインターネットでPython MecabをCGIから使う
さくらインターネットのPHPでAnalytics-G4 APIを使う
インクルードパスの調べ方
【Git】特定ファイルを除外する.gitignore
【Ubuntu/Debian】NVIDIA関係のドライバを自動アップデートさせない
【Python】Spacyを使用して文章から出発地と目的地を抜き出す
【人気の記事】【全部の記事】
進研ゼミチャレンジタッチをAndroid端末化する【Windows10】リモートデスクトップ間のコピー&ペーストができなくなった場合の対処法
【Apache】サーバーに同時接続可能なクライアント数を調整する
GitLabにHTTPS経由でリポジトリをクローン&読み書きを行う
Windows版Google Driveが使用中と言われアンインストールできない場合
【Linux】iconv/libiconvをソースコードからインストール
【C/C++】小数点以下の切り捨て・切り上げ・四捨五入
Windows11+WSL2でUbuntuを使う【2】ブリッジ接続+固定IPの設定
【PHP】Mail/mimeDecodeを使ってメールの中身を解析(準備編)
Googleファミリーリンクで子供の端末の現在地がエラーで取得できない場合
【カテゴリーリンク】
Android
iPhone/iPad
Flutter
MacOS
Windows
Debian
Ubuntu
CentOS
FreeBSD
RaspberryPI
HTML/CSS
C/C++
PHP
Java
JavaScript
Node.js
Swift
Python
MatLab
Amazon/AWS
CORESERVER
Google
仮想通貨
LINE
OpenAI/ChatGPT
IBM Watson
Microsoft Azure
Xcode
VMware
MySQL
PostgreSQL
Redis
Groonga
Git/GitHub
Apache
nginx
Postfix
SendGrid
Hackintosh
Hardware
Fate/Grand Order
ウマ娘
将棋
ドラレコ