範囲の区分化や区分化されているかの判定を行います。
範囲の指定方法は、
・std::xxx(C++03): 対象の範囲 [first, last) のイテレータ―を指定します。
・std::ranges::xxx(C++20): 対象の範囲 [first, last) のイテレータ―を指定します。
・std::ranges::xxx(C++20): 対象の範囲を直接指定します。
条件判定に関数を指定します。※
std::ranges::xxx(C++20): 射影(projection)関数を指定できるものがあります。※
出力先は、既存の範囲に上書きするものと、別途出力先のイテレーターを指定するものがあります。※
※詳細についてはこちらを参照してください。
https://mappuri.com/program/cpp20-algorithm/
区分化
partition
範囲を条件で区分化します。
範囲は双方向(C++03)順方向(C++11)に読み書き可能である必要があります。
partition_copy
範囲を条件で区分化して出力します。
stable_partition
範囲を順序を維持して条件で区分化します。
範囲は双方向(C++03)順方向(C++11)に読み書き可能である必要があります。
partition, partition_copy, stable_partition のサンプル(C++03)
#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 << " 値:";
std::string delim = "";
for (auto i = first; i != last; ++i, delim = ", ") {
std::cout << delim << *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[]) {
{
// 範囲を条件で区分化します。(C++03)
std::vector<int> r = { 3, 2, 5, 1, 4 };
auto partition = std::partition(r.begin(), r.end(),
[](int x) { return x % 2 == 0; }); // 偶数
output(r, r.begin(), partition); // 範囲:[0, 2) 値:4, 2
output(r, partition, r.end()); // 範囲:[2, 5) 値:5, 1, 3
}
{
// 範囲を条件で区分化して出力します。(C++11)
std::vector<int> r = { 3, 2, 5, 1, 4 };
std::vector<int> o1(5), o2(5);
auto partition_copy = std::partition_copy(r.begin(), r.end(), o1.begin(), o2.begin(),
[](int x) { return x % 2 == 0; }); // 偶数
output(o1, o1.begin(), partition_copy.first); // 範囲:[0, 2) 値:2, 4
output(o2, o2.begin(), partition_copy.second); // 範囲:[0, 3) 値:3, 5, 1
}
{
// 範囲を順序を維持して条件で区分化します。(C++03)
std::vector<int> r = { 3, 2, 5, 1, 4 };
auto stable_partition = std::stable_partition(r.begin(), r.end(),
[](int x) { return x % 2 == 0; }); // 偶数
output(r, r.begin(), stable_partition); // 範囲:[0, 2) 値:2, 4
output(r, stable_partition, r.end()); // 範囲:[2, 5) 値:3, 5, 1
}
return 0;
}
partition, partition_copy, stable_partition のサンプル(C++20 range)
#include <algorithm>
#include <iostream>
#include <vector>
int main(int argc, char* argv[]) {
{
// 範囲を条件で区分化します。(C++20)
std::vector<int> r = { 3, 2, 5, 1, 4 };
auto partition = std::ranges::partition(r,
[](int x) { return x % 2 == 0; }); // 偶数
output(r, r.begin(), partition.begin()); // 範囲:[0, 2) 値:4, 2
output(r, partition.begin(), partition.end()); // 範囲:[2, 5) 値:5, 1, 3
}
{
// 範囲を条件で区分化して出力します。(C++20)
std::vector<int> r = { 3, 2, 5, 1, 4 };
std::vector<int> o1(5), o2(5);
auto partition_copy = std::ranges::partition_copy(r, o1.begin(), o2.begin(),
[](int x) { return x % 2 == 0; }); // 偶数
output(o1, o1.begin(), partition_copy.out1); // 範囲:[0, 2) 値:2, 4
output(o2, o2.begin(), partition_copy.out2); // 範囲:[0, 3) 値:3, 5, 1
}
{
// 範囲を順序を維持して条件で区分化します。(C++20)
std::vector<int> r = { 3, 2, 5, 1, 4 };
auto stable_partition = std::ranges::stable_partition(r,
[](int x) { return x % 2 == 0; }); // 偶数
output(r, r.begin(), stable_partition.begin()); // 範囲:[0, 2) 値:2, 4
output(r, stable_partition.begin(), stable_partition.end()); // 範囲:[2, 5) 値:3, 5, 1
}
return 0;
}
区分化判定
is_partitioned
範囲が条件で区分化されているか判定します。
partition_point
範囲の条件で区分化されている位置を取得します。
is_partitioned, partition_point のサンプル(C++11)
#include <algorithm>
#include <iostream>
#include <vector>
int main(int argc, char* argv[]) {
{
// 範囲が条件で区分化されているか判定します。(C++11)
std::vector<int> r = { 2, 4, 3, 5, 1 };
bool is_partitioned = std::is_partitioned(r.begin(), r.end(),
[](int x) { return x % 2 == 0; });
std::cout << "is_partitioned = " << std::boolalpha << is_partitioned << std::endl; // is_partitioned = true
}
{
// 範囲の条件で区分化されている位置を取得します。(C++11)
std::vector<int> r = { 2, 4, 3, 5, 1 };
auto partition_point = std::partition_point(r.begin(), r.end(),
[](int x) { return x % 2 == 0; });
output(r, partition_point); // 位置:2 値:3
}
return 0;
}
is_partitioned, partition_point のサンプル(C++20 range)
#include <algorithm>
#include <iostream>
#include <vector>
int main(int argc, char* argv[]) {
{
// 範囲が条件で区分化されているか判定します。(C++20)
std::vector<int> r = { 2, 4, 3, 5, 1 };
bool is_partitioned = std::ranges::is_partitioned(r,
[](int x) { return x % 2 == 0; });
std::cout << "is_partitioned = " << std::boolalpha << is_partitioned << std::endl; // is_partitioned = true
}
{
// 範囲の条件で区分化されている位置を取得します。(C++20)
std::vector<int> r = { 2, 4, 3, 5, 1 };
auto partition_point = std::ranges::partition_point(r,
[](int x) { return x % 2 == 0; });
output(r, partition_point); // 位置:2 値:3
}
return 0;
}
コメント