要素・範囲・オブジェクトの入れ替え (C++03 – C++20)

C++

要素・範囲・オブジェクトを入れ替える関数の説明です。

概要

要素・範囲・オブジェクトの入れ替えを行えます。
範囲の指定方法は、
・std::xxx(C++03): 対象の範囲 [first, last) のイテレータ―を指定します。
・std::ranges::xxx(C++20): 対象の範囲 [first, last) のイテレータ―を指定します。
・std::ranges::xxx(C++20): 対象の範囲を直接指定します。
出力先は、既存の範囲に上書きするものと、別途出力先のイテレーターを指定するものがあります。※
※詳細についてはこちらを参照してください。
https://mappuri.com/program/cpp20-algorithm/

要素・範囲・オブジェクトの入れ替え

iter_swap

2つのイテレーターの要素を入れ替えます。

swap_ranges

2つの範囲を入れ替えます。
同じサイズの範囲が入れ替えられます。範囲2の last が指定されていない場合は範囲1のサイズ、それ以外は範囲1,2の小さいほうのサイズになります。

swap

2つのオブジェクトを入れ替えます。
組み込み型の変数や、配列、STL コンテナなどを指定できます。

iter_swap, swap_ranges, swap のサンプル (C++03, C++11)

#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;
}

#include <algorithm>
#include <iostream>
#include <vector>

int main(int argc, char* argv[]) {
	{
		// 2つのイテレーターの要素を入れ替えます。(C++03)
		std::vector<int> r1 = { 1, 2, 3, 4, 5 };
		std::vector<int> r2 = { 10, 20, 30, 40, 50, 60 };
		std::iter_swap(r1.begin() + 2, r2.begin() + 3);
		output(r1, r1.begin(), r1.end()); // 範囲:[0, 5) 値:1, 2, 40, 4, 5
		output(r2, r2.begin(), r2.end()); // 範囲:[0, 6) 値:10, 20, 30, 3, 50, 60
	}
	{
		// 2つの範囲を入れ替えます。(C++03)
		std::vector<int> r1 = { 1, 2, 3, 4, 5 };
		std::vector<int> r2 = { 10, 20, 30, 40, 50, 60 };
		std::swap_ranges(r1.begin(), r1.end(), r2.begin());
		output(r1, r1.begin(), r1.end()); // 範囲:[0, 5) 値:10, 20, 30, 40, 50
		output(r2, r2.begin(), r2.end()); // 範囲:[0, 6) 値:1, 2, 3, 4, 5, 60
	}
	{
		// 2つのオブジェクトを入れ替えます。(C++11)
		std::vector<int> r1 = { 1, 2, 3, 4, 5 };
		std::vector<int> r2 = { 10, 20, 30, 40, 50, 60 };
		std::swap(r1, r2);
		output(r1, r1.begin(), r1.end()); // 範囲:[0, 6) 値:10, 20, 30, 40, 50, 60
		output(r2, r2.begin(), r2.end()); // 範囲:[0, 5) 値:1, 2, 3, 4, 5
	}
	return 0;
}

swap_ranges, swap のサンプル (C++20 range)

#include <algorithm>
#include <iostream>
#include <vector>

int main(int argc, char* argv[]) {
	{
		// 2つの範囲を入れ替えます。(C++20)
		std::vector<int> r1 = { 1, 2, 3, 4, 5 };
		std::vector<int> r2 = { 10, 20, 30, 40, 50, 60 };
		std::ranges::swap_ranges(r1, r2);
		output(r1, r1.begin(), r1.end()); // 範囲:[0, 5) 値:10, 20, 30, 40, 50
		output(r2, r2.begin(), r2.end()); // 範囲:[0, 6) 値:1, 2, 3, 4, 5, 60
	}
	{
		// 2つのオブジェクトを入れ替えます。(C++20)
		std::vector<int> r1 = { 1, 2, 3, 4, 5 };
		std::vector<int> r2 = { 10, 20, 30, 40, 50, 60 };
		std::ranges::swap(r1, r2);
		output(r1, r1.begin(), r1.end()); // 範囲:[0, 6) 値:10, 20, 30, 40, 50, 60
		output(r2, r2.begin(), r2.end()); // 範囲:[0, 5) 値:1, 2, 3, 4, 5
	}
	return 0;
}

要素の入れ替え・抽出

reverse

要素を逆順にします。

reverse_copy

要素を逆順にして出力します。

rotate

要素を指定位置で入れ替えます。

rotate_copy

要素を指定位置で入れ替えて出力します。

shuffle

要素をランダムで並び変えます。

sample

要素をランダムで指定数抽出します。

shift_left

要素を左に移動します。

shift_right

要素を右に移動します。

reverse, rotate, shuffle, sample, shift_left, shift_right, … のサンプル (C++03 – C++20)

#include <algorithm>
#include <iostream>
#include <random>
#include <vector>

int main(int argc, char* argv[]) {
	{
		// 要素を逆順にします。(C++03)
		std::vector<int> r = { 1, 2, 3, 4, 5 };
		std::reverse(r.begin(), r.end());
		output(r, r.begin(), r.end()); // 範囲:[0, 5) 値:5, 4, 3, 2, 1
	}
	{
		// 要素を逆順にして出力します。(C++03)
		std::vector<int> r = { 1, 2, 3, 4, 5 };
		std::vector<int> o(r.size());
		auto reverse_copy = std::reverse_copy(r.begin(), r.end(), o.begin());
		output(o, o.begin(), reverse_copy); // 範囲:[0, 5) 値:5, 4, 3, 2, 1
	}
	{
		// 要素を指定位置で入れ替えます。(C++03)
		std::vector<int> r = { 1, 2, 3, 4, 5 };
		std::rotate(r.begin(), std::next(r.begin(), 3), r.end());
		output(r, r.begin(), r.end()); // 範囲:[0, 5) 値:4, 5, 1, 2, 3
	}
	{
		// 要素を指定位置で入れ替えて出力します。(C++03)
		std::vector<int> r = { 1, 2, 3, 4, 5 };
		std::vector<int> o(r.size());
		auto rotate_copy = std::rotate_copy(r.begin(), std::next(r.begin(), 3), r.end(), o.begin());
		output(o, o.begin(), rotate_copy); // 範囲:[0, 5) 値:4, 5, 1, 2, 3
	}
	{
		// 要素をランダムで並び変えます。(C++11)
		std::vector<int> r = { 1, 2, 3, 4, 5 };
		std::random_device rd;
		std::mt19937 re{rd()};
		std::shuffle(r.begin(), r.end(), re);
		output(r, r.begin(), r.end()); // 範囲:[0, 5) 値:4, 3, 1, 5, 2
	}
	{
		// 要素をランダムで指定数抽出します。(C++17)
		std::vector<int> r = { 1, 2, 3, 4, 5 };
		std::vector<int> o(r.size());
		std::random_device rd;
		std::mt19937 re{rd()};
		auto sample = std::sample(r.begin(), r.end(), o.begin(), 3, re);
		output(o, o.begin(), sample); // 範囲:[0, 3) 値:1, 2, 5
	}
	{
		// 要素を左に移動します。(C++20)
		std::vector<int> r = { 1, 2, 3, 4, 5 };
		auto shift_left = std::shift_left(r.begin(), r.end(), 3);
		output(r, r.begin(), r.end()); // 範囲:[0, 5) 値:4, 5, 3, 4, 5 <- 全体
		output(r, r.begin(), shift_left); // 範囲:[0, 2) 値:4, 5 <- 移動後範囲
	}
	{
		// 要素を右に移動します。(C++20)
		std::vector<int> r = { 1, 2, 3, 4, 5 };
		auto shift_right = std::shift_right(r.begin(), r.end(), 3);
		output(r, r.begin(), r.end()); // 範囲:[0, 5) 値:1, 2, 3, 1, 2 <- 全体
		output(r, shift_right, r.end()); // 範囲:[3, 5) 値:1, 2 <- 移動後範囲
	}
	return 0;
}

reverse, rotate, shuffle, sample, … のサンプル (C++20 range)

#include <algorithm>
#include <iostream>
#include <random>
#include <vector>

int main(int argc, char* argv[]) {
	{
		// 要素を逆順にします。(C++20)
		std::vector<int> r = { 1, 2, 3, 4, 5 };
		std::ranges::reverse(r);
		output(r, r.begin(), r.end()); // 範囲:[0, 5) 値:5, 4, 3, 2, 1
	}
	{
		// 要素を逆順にして出力します。(C++20)
		std::vector<int> r = { 1, 2, 3, 4, 5 };
		std::vector<int> o(r.size());
		auto reverse_copy = std::ranges::reverse_copy(r, o.begin());
		output(o, o.begin(), reverse_copy.out); // 範囲:[0, 5) 値:5, 4, 3, 2, 1
	}
	{
		// 要素を指定位置で入れ替えます。(C++20)
		std::vector<int> r = { 1, 2, 3, 4, 5 };
		std::ranges::rotate(r, std::next(r.begin(), 3));
		output(r, r.begin(), r.end()); // 範囲:[0, 5) 値:4, 5, 1, 2, 3
	}
	{
		// 要素を指定位置で入れ替えて出力します。(C++20)
		std::vector<int> r = { 1, 2, 3, 4, 5 };
		std::vector<int> o(r.size());
		auto rotate_copy = std::ranges::rotate_copy(r, std::next(r.begin(), 3), o.begin());
		output(o, o.begin(), rotate_copy.out); // 範囲:[0, 5) 値:4, 5, 1, 2, 3
	}
	{
		// 要素をランダムで並び変えます。(C++20)
		std::vector<int> r = { 1, 2, 3, 4, 5 };
		std::random_device rd;
		std::mt19937 re{rd()};
		std::ranges::shuffle(r, re);
		output(r, r.begin(), r.end()); // 範囲:[0, 5) 値:4, 3, 1, 5, 2
	}
	{
		// 要素をランダムで指定数抽出します。(C++20)
		std::vector<int> r = { 1, 2, 3, 4, 5 };
		std::vector<int> o(r.size());
		std::random_device rd;
		std::mt19937 re{rd()};
		auto sample = std::ranges::sample(r, o.begin(), 3, re);
		output(o, o.begin(), sample); // 範囲:[0, 3) 値:1, 2, 5
	}
	return 0;
}

コメント

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