コレクション同士を先頭から比較する関数の説明です。
概要
2つの範囲の要素はソート済みの必要があります。
要素はシーケンシャルアクセスが必要です。一部でランダムアクセスがないと計算量が大きくなります。
コレクションの指定方法は基本的に以下の通りですが、例外があるので個別の関数を参照してください。
・std::xxx: 対象の範囲 [first, last) のイテレータ―を指定します。(C++14)
・・範囲2の last を省略した場合は、範囲1の大きさと同じ範囲が対象になります。(C++03)
・std::ranges::xxx(C++20): 対象の範囲 [first, last) のイテレータ―を指定します。
・・範囲2の last を省略した場合は、範囲1の大きさと同じ範囲が対象になります。
・std::ranges::xxx(C++20): 対象の範囲を直接指定します。
比較関数は関数ごとに異なります。
詳細についてはこちらを参照してください。https://mappuri.com/program/cpp20-algorithm/
関数の説明
equal
2つの範囲が等しいか比較します。
r2 の last を省略した場合は、r1 の大きさと同じ範囲が対象になります。(C++03)
r2 の last を指定した場合、r1, r2 の大きさの比較が行われます。その場合ランダムアクセス可能でないと計算量が大きくなります。(C++14)
比較関数には、等しい(==)ときに true を返す関数を指定します。
mismatch
2つの範囲が等しくない位置を検索します。
r2 の last を省略した場合は、r1 の大きさと同じ範囲が対象になります。(C++03)
r2 の last を指定するには C++14 以上が必要です。(C++14)
比較関数には、要素が等しい(==)ときに true を返す関数を指定します。
一致しなかった位置、または終端を返します。
lexicographical_compare
r1 が r2 より辞書的に小さいか比較します。
比較関数には、要素がより小さい(<)ときに true を返す関数を指定します。
r1 が r2 より小さいときに true を返します。
lexicographical_compare_three_way
r1 と r2 を辞書的に三方比較します。
C++20 の std::lexicographical_compare_three_way イテレーター版しかありません。
比較関数には、三方比較(<=>)結果を返す関数を指定します。
r1 と r2 の三方比較結果を返します。
サンプルプログラム
C++03/14/20 イテレーター指定
#include <iostream>
/** r 内の [first, last) の範囲と値を出力 範囲:[0, 9) 値:1 2 3 4 5 4 5 6 6 */
template<class T, class U, class V>
static void output(T&& r, U&& first, V&& last) {
std::cout << "範囲:[" << std::distance(std::begin(r), first) << ", " << std::distance(std::begin(r), last) << ")";
std::cout << " 値:";
for (auto i = first; i != last; ++i) {
std::cout << *i << " ";
}
std::cout << std::endl;
}
/** r 内の it の位置と値を出力 位置:2 値:3 */
template<class T, class U>
static void output(T&& r, U&& it) {
std::cout << "位置:" << std::distance(std::begin(r), it);
std::cout << " 値:";
if (it == std::end(r) || &*it == nullptr) {
std::cout << "end";
} else {
std::cout << *it;
}
std::cout << std::endl;
}
#include <algorithm>
#include <iostream>
#include <vector>
int main(int argc, char* argv[]) {
std::vector<int> r1 = { 1, 2, 3, 4, 5 };
std::vector<int> r2 = { 1, 2, 3, 4, 5, 6 };
// 2つの範囲が等しいか比較します。
auto equal = std::equal(r1.begin(), r1.end(), r2.begin());
std::cout << std::boolalpha << equal << std::endl;
// true
// 2つの範囲が等しいか比較します。(C++14)
auto equal2 = std::equal(r1.begin(), r1.end(), r2.begin(), r2.end());
std::cout << std::boolalpha << equal2 << std::endl;
// false
// 比較関数には、等しい(==)ときに true を返す関数を指定します。
auto equal3 = std::equal(r1.begin(), r1.end(), r2.begin(),
[](int a, int b) { std::cout << a << "," << b << " "; return a == b; });
std::cout << std::boolalpha << equal3 << std::endl;
// 1,1 2,2 3,3 4,4 5,5 true
// 2つの範囲が等しくない位置を検索します。
auto mismatch = std::mismatch(r1.begin(), r1.end(), r2.begin());
output(r1, mismatch.first); // 位置:5 値:end
output(r2, mismatch.second); // 位置:5 値:6
// r1 が r2 より辞書的に小さいか比較します。
auto lexicographical_compare = std::lexicographical_compare(r1.begin(), r1.end(), r2.begin(), r2.end());
std::cout << std::boolalpha << lexicographical_compare << std::endl;
// true
// r1 と r2 を辞書的に三方比較します。
#if __cplusplus >= 202002L
auto lexicographical_compare_three_way = std::lexicographical_compare_three_way(r1.begin(), r1.end(), r2.begin(), r2.end());
std::cout << std::boolalpha
<< "<:" << (lexicographical_compare_three_way < 0)
<< " ==:" << (lexicographical_compare_three_way == 0)
<< " >:" << (lexicographical_compare_three_way > 0)
<< std::endl;
// <:true ==:false >:false
#else
std::cout << "not supported. std::lexicographical_compare_three_way C++20; #if __cplusplus >= 202002L: " << __cplusplus << std::endl;
#endif
return 0;
}
C++20 range指定
#include <algorithm>
#include <iostream>
#include <vector>
int main(int argc, char* argv[]) {
std::vector<int> r1 = { 1, 2, 3, 4, 5 };
std::vector<int> r2 = { 1, 2, 3, 4, 5, 6 };
// 2つの範囲が等しいか比較します。
auto equal = std::ranges::equal(r1, r2);
std::cout << std::boolalpha << equal << std::endl;
// false
// 比較関数には、等しい(==)ときに true を返す関数を指定します。
auto equal3 = std::ranges::equal(r1, r2,
[](int a, int b) { std::cout << a << "," << b << " "; return a == b; });
std::cout << std::boolalpha << equal3 << std::endl;
// false
// 2つの範囲が等しくない位置を検索します。
auto mismatch = std::ranges::mismatch(r1, r2);
output(r1, mismatch.in1); // 位置:5 値:end
output(r2, mismatch.in2); // 位置:5 値:6
// r1 が r2 より辞書的に小さいか比較します。
auto lexicographical_compare = std::ranges::lexicographical_compare(r1, r2);
std::cout << std::boolalpha << lexicographical_compare << std::endl;
// true
return 0;
}
コメント