カテゴリー【C/C++】
【C++】shared_ptrで生成したクラス配列を複数の優先順位でソートする
POSTED BY
2024-12-16
2024-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/管理人】
自営業プログラマーです。お仕事ください!ご連絡は以下アドレスまでお願いします★
【キーワード検索】
【最近の記事】【全部の記事】
LetsEncrypt/certbotの証明書自動更新がエラーになる場合Wav2Lipのオープンソース版を改造して外部から呼べるAPI化する
Wav2Lipのオープンソース版で静止画の口元のみを動かして喋らせる
【iOS】アプリアイコン・ロゴ画像の作成・設定方法
オープンソースリップシンクエンジンSadTalkerをAPI化してアプリから呼ぶ【2】
オープンソースリップシンクエンジンSadTalkerをAPI化してアプリから呼ぶ【1】
【Xcode】iPhone is not available because it is unpairedの対処法
【Let's Encrypt】Failed authorization procedure 503の対処法
【Debian】古いバージョンでapt updateしたら404 not foundでエラーになる場合
ファイアウォール内部のWindows11 PCにmacOS Sequoiaからリモートデスクトップする
【人気の記事】【全部の記事】
進研ゼミチャレンジタッチをAndroid端末化する【Windows10】リモートデスクトップ間のコピー&ペーストができなくなった場合の対処法
Windows11+WSL2でUbuntuを使う【2】ブリッジ接続+固定IPの設定
【C/C++】小数点以下の切り捨て・切り上げ・四捨五入
GitLabにHTTPS経由でリポジトリをクローン&読み書きを行う
Windows11のコマンドプロンプトでテキストをコピーする
Googleスプレッドシートを編集したら自動で更新日時を入れる
タスクスケジューラで変更を適用できません。ユーザーアカウントが不明であるか、パスワードが正しくないか、またはユーザーアカウントにタスクを変更する許可がありません。と出た
【Apache】サーバーに同時接続可能なクライアント数を調整する
【Raspberry Piメモ・3】オンボード無線LANでWi-fi Direct対応機器に接続する
【カテゴリーリンク】
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
ウマ娘
将棋
ドラレコ