範囲の要素を削除・重複削除する関数の説明です。
概要
配列やコンテナの要素の変更を行えます。
範囲はシーケンシャルアクセスが必要です。
範囲の指定方法は、
・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/
要素の削除
remove
指定した値の要素を削除します。
std::ranges::xxx(C++20): 射影(projection)関数を指定できます。
削除された後ろの要素の値は前に詰めれらます。残った範囲は切り詰められず、範囲のサイズは変更されません。戻り値でこの位置や範囲を返すので、必要に応じて erase 関数などで消去します。
remove_if
指定した条件の要素を削除します。
条件判定の関数を指定します。
std::ranges::xxx(C++20): 射影(projection)関数を指定できます。
削除された後ろの要素の値は前に詰めれらます。残った範囲は切り詰められず、範囲のサイズは変更されません。戻り値でこの位置や範囲を返すので、必要に応じて erase 関数などで消去します。
remove_copy
指定した要素を削除して出力します。
出力先のイテレーターを指定します。
std::ranges::xxx(C++20): 射影(projection)関数を指定できます。
remove_copy_if
指定した要素を削除して出力します。
出力先のイテレーターを指定します。
条件判定の関数を指定します。
std::ranges::xxx(C++20): 射影(projection)関数を指定できます。
remove, … のサンプル (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;
}
#include <algorithm>
#include <iostream>
#include <vector>
int main(int argc, char* argv[]) {
{
// 指定した値の要素を削除します。(C++03)
std::vector<int> r = { 1, 2, 3, 4, 5 };
auto remove = std::remove(r.begin(), r.end(), 3);
output(r, r.begin(), remove); // 範囲:[0, 4) 値:1, 2, 4, 5 <- 削除後範囲
output(r, r.begin(), r.end()); // 範囲:[0, 5) 値:1, 2, 4, 5, 5 <- 全体
// 削除後範囲に切り詰める(以降同様)
r.erase(remove, r.end());
output(r, r.begin(), r.end()); // 範囲:[0, 4) 値:1, 2, 4, 5 <- 全体
}
{
// 指定した条件の要素を削除します。(C++03)
std::vector<int> r = { 1, 2, 3, 4, 5 };
auto remove_if = std::remove_if(r.begin(), r.end(), [](int x) { return x & 1; }); // 奇数
output(r, r.begin(), remove_if); // 範囲:[0, 2) 値:2, 4
}
{
// 指定した要素を削除して出力します。(C++03)
std::vector<int> r = { 1, 2, 3, 4, 5 };
std::vector<int> o(r.size());
auto remove_copy = std::remove_copy(r.begin(), r.end(), o.begin(), 3);
output(o, o.begin(), remove_copy); // 範囲:[0, 4) 値:1, 2, 4, 5
}
{
// 指定した条件の要素を削除して出力します。(C++03)
std::vector<int> r = { 1, 2, 3, 4, 5 };
std::vector<int> o(r.size());
auto remove_copy_if = std::remove_copy_if(r.begin(), r.end(), o.begin(), [](int x) { return x & 1; }); // 奇数
output(o, o.begin(), remove_copy_if); // 範囲:[0, 2) 値:2, 4
}
return 0;
}
remove, … のサンプル (C++20 range)
#include <algorithm>
#include <iostream>
#include <vector>
int main(int argc, char* argv[]) {
{
// 指定した値の要素を削除します。(C++20, range)
std::vector<int> r = { 1, 2, 3, 4, 5 };
auto remove = std::ranges::remove(r, 3);
output(r, r.begin(), remove.begin()); // 範囲:[0, 4) 値:1, 2, 4, 5 <- 削除後範囲
output(r, r.begin(), r.end()); // 範囲:[0, 5) 値:1, 2, 4, 5, 5 <- 全体
// 削除後範囲に切り詰める(以降同様)
r.erase(remove.begin(), remove.end());
output(r, r.begin(), r.end()); // 範囲:[0, 4) 値:1, 2, 4, 5 <- 全体
}
{
// 指定した条件の要素を削除します。(C++20, range)
std::vector<int> r = { 1, 2, 3, 4, 5 };
auto remove_if = std::ranges::remove_if(r, [](int x) { return x & 1; }); // 奇数
output(r, r.begin(), remove_if.begin()); // 範囲:[0, 2) 値:2, 4
}
{
// 指定した要素を削除して出力します。(C++20, range)
std::vector<int> r = { 1, 2, 3, 4, 5 };
std::vector<int> o(r.size());
auto remove_copy = std::ranges::remove_copy(r, o.begin(), 3);
output(o, o.begin(), remove_copy.out); // 範囲:[0, 4) 値:1, 2, 4, 5
}
{
// 指定した条件の要素を削除して出力します。(C++20, range)
std::vector<int> r = { 1, 2, 3, 4, 5 };
std::vector<int> o(r.size());
auto remove_copy_if = std::ranges::remove_copy_if(r, o.begin(), [](int x) { return x & 1; }); // 奇数
output(o, o.begin(), remove_copy_if.out); // 範囲:[0, 2) 値:2, 4
}
return 0;
}
隣り合う重複要素の削除
unique
隣り合う重複する要素を削除します。
必要に応じて条件判定の関数を指定できます。
std::ranges::xxx(C++20): 射影(projection)関数を指定できます。
離れた位置にある重複する要素は削除されません。必要に応じてあらかじめ sort 関数などでソートしておきます。
削除された後ろの要素の値は前に詰めれらます。残った範囲は切り詰められず、範囲のサイズは変更されません。戻り値でこの位置や範囲を返すので、必要に応じて erase 関数などで消去します。
unique_copy
隣り合う重複要素を削除して出力します。
出力先のイテレーターを指定します。
必要に応じて条件判定の関数を指定できます。
std::ranges::xxx(C++20): 射影(projection)関数を指定できます。
離れた位置にある重複する要素は削除されません。必要に応じてあらかじめ sort 関数などでソートしておきます。
unique, unique_copy のサンプル (C++03)
#include <algorithm>
#include <iostream>
#include <vector>
int main(int argc, char* argv[]) {
{
// 隣り合う重複する要素を削除します。(C++03)
std::vector<int> r = { 1, 2, 2, 4, 2, 2, 5 };
auto unique = std::unique(r.begin(), r.end());
output(r, r.begin(), unique); // 範囲:[0, 5) 値:1, 2, 4, 2, 5 <- 削除後範囲
output(r, r.begin(), r.end()); // 範囲:[0, 7) 値:1, 2, 4, 2, 5, 2, 5 <- 全体
// 削除後範囲に切り詰める(以降同様)
r.erase(unique, r.end());
output(r, r.begin(), r.end()); // 範囲:[0, 5) 値:1, 2, 4, 2, 5 <- 全体
}
{
// 隣り合う指定した条件で重複する要素を削除します。(C++03)
std::vector<int> r = { 11, 21, 22, 41, 21, 22, 51 };
auto unique = std::unique(r.begin(), r.end(),
[](int x, int y) { return x / 10 == y / 10; }); // 10の位で比較
output(r, r.begin(), unique); // 範囲:[0, 5) 値:11, 21, 41, 21, 51
}
{
// 隣り合う重複要素を削除して出力します。(C++03)
std::vector<int> r = { 1, 2, 2, 4, 2, 2, 5 };
std::vector<int> o(r.size());
auto unique_copy = std::unique_copy(r.begin(), r.end(), o.begin());
output(o, o.begin(), unique_copy); // 範囲:[0, 5) 値:1, 2, 4, 2, 5
}
{
// 隣り合う指定した条件で重複する要素を削除して出力します。(C++03)
std::vector<int> r = { 11, 21, 22, 41, 21, 22, 51 };
std::vector<int> o(r.size());
auto unique_copy = std::unique_copy(r.begin(), r.end(), o.begin(),
[](int x, int y) { return x / 10 == y / 10; }); // 10の位で比較
output(o, o.begin(), unique_copy); // 範囲:[0, 5) 値:11, 21, 41, 21, 51
}
return 0;
}
unique, unique_copy のサンプル (C++20 range)
#include <algorithm>
#include <iostream>
#include <vector>
int main(int argc, char* argv[]) {
{
// 隣り合う重複する要素を削除します。(C++20, range)
std::vector<int> r = { 1, 2, 2, 4, 2, 2, 5 };
auto unique = std::ranges::unique(r);
output(r, r.begin(), unique.begin()); // 範囲:[0, 5) 値:1, 2, 4, 2, 5 <- 削除後範囲
output(r, r.begin(), r.end()); // 範囲:[0, 7) 値:1, 2, 4, 2, 5, 2, 5 <- 全体
// 削除後範囲に切り詰める(以降同様)
r.erase(unique.begin(), unique.end());
output(r, r.begin(), r.end()); // 範囲:[0, 5) 値:1, 2, 4, 2, 5 <- 全体
}
{
// 隣り合う指定した条件で重複する要素を削除します。(C++20, range)
std::vector<int> r = { 11, 21, 22, 41, 21, 22, 51 };
auto unique = std::ranges::unique(r,
[](int x, int y) { return x / 10 == y / 10; }); // 10の位で比較
output(r, r.begin(), unique.begin()); // 範囲:[0, 5) 値:11, 21, 41, 21, 51
}
{
// 隣り合う重複要素を削除して出力します。(C++20, range)
std::vector<int> r = { 1, 2, 2, 4, 2, 2, 5 };
std::vector<int> o(r.size());
auto unique_copy = std::ranges::unique_copy(r, o.begin());
output(o, o.begin(), unique_copy.out); // 範囲:[0, 5) 値:1, 2, 4, 2, 5
}
{
// 隣り合う指定した条件で重複する要素を削除して出力します。(C++20, range)
std::vector<int> r = { 11, 21, 22, 41, 21, 22, 51 };
std::vector<int> o(r.size());
auto unique_copy = std::ranges::unique_copy(r, o.begin(),
[](int x, int y) { return x / 10 == y / 10; }); // 10の位で比較
output(o, o.begin(), unique_copy.out); // 範囲:[0, 5) 値:11, 21, 41, 21, 51
}
return 0;
}
コメント