範囲の区分化 (C++03 – C++20)

C++

範囲の区分化や区分化されているかの判定を行います。
範囲の指定方法は、
・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;
}

コメント

タイトルとURLをコピーしました