Все сводится к созданию функций сравнения, которые обрабатывают перестановки значений в контейнере как равные.
Концепция для этого заключается в следующем:
- Скопируйте значения из контейнеров какими бы они ни были, в
std::vector
- Затем сортируйте
std::vector
s - Затем используйте существующую функцию сравнения из
std::vector
Как Например, я создал обобщенную c лямбду, которая будет выполнять эту задачу. Пожалуйста, смотрите:
auto cmpPermLess = [](const auto& c1, const auto& c2) -> bool {
std::vector v1(c1.begin(), c1.end());
std::vector v2(c2.begin(), c2.end());
std::sort(v1.begin(), v1.end());
std::sort(v2.begin(), v2.end());
return v1 < v2;
};
Аналогичный подход можно использовать и для других сравнений.
Конечно, вы также можете определить простые другие операторные перегрузки или функции сравнения. Но механизм всегда один и тот же. Скопируйте параметры в std::vector
s, затем отсортируйте их, а затем сравните std::vectors
.
Теперь я покажу некоторый код драйвера для проверки всего этого:
#include <iostream>
#include <string>
#include <vector>
#include <algorithm>
#include <set>
#include <array>
#include <iterator>
// A generic Lambda for comparing containers and ignoring permutations
// Less than
auto cmpPermLess = [](const auto& c1, const auto& c2) -> bool { std::vector v1(c1.begin(), c1.end());
std::vector v2(c2.begin(), c2.end());
std::sort(v1.begin(), v1.end());
std::sort(v2.begin(), v2.end());
return v1 < v2;
};
// Equal
auto cmpPermEqual = [](const auto& c1, const auto& c2) -> bool { std::vector v1(c1.begin(), c1.end());
std::vector v2(c2.begin(), c2.end());
std::sort(v1.begin(), v1.end());
std::sort(v2.begin(), v2.end());
return v1 == v2;
};
// Example for Face definition
using Face = std::array<int, 3>;
// Example for a less than operator for Face
bool operator<(const Face& f1, const Face& f2) { return cmpPermLess(f1, f2); };
// Some test code for syntax check.
int main() {
// Define a vector with Faces
std::vector<Face> vf{ {0,1,2},{0,1,3},{1,2,0},{3,1,0},{1,2,3},{0,3,1},{1,3,0}};
std::cout << "\n\nOriginal Vector:\n";
for (const Face& f : vf) std::cout << f[0] << ' ' << f[1] << ' ' << f[2] << '\n';
// And some standalong faces
Face f1{ 2,1,0 }, f2{ 0,1,3 };
// Check less than operator
if (f1 < f2) {
std::cout << "\n\nF1 is less then F2\n";
}
// Check comparator for usage in algorithms
std::sort(vf.begin(), vf.end(), cmpPermLess);
std::cout << "\n\nSorted vector:\n";
for (const Face& f : vf) std::cout << f[0] << ' ' << f[1] << ' ' << f[2] << '\n';
// And check COmparator for usage in other containers
std::set<Face, decltype(cmpPermLess)> sf(vf.begin(),vf.end());
std::cout << "\n\nSet with unique elements:\n";
for (const Face& f : sf) std::cout << f[0] << ' ' << f[1] << ' ' << f[2] << '\n';
// Check comparator for usage in algorithms
std::sort(vf.begin(), vf.end(), cmpPermLess);
std::cout << "\n\nSorted vector:\n";
for (const Face& f : vf) std::cout << f[0] << ' ' << f[1] << ' ' << f[2] << '\n';
// Now the vector is sorted. Search doubles and delete them
for (std::vector<Face>::iterator it = std::adjacent_find(vf.begin(), vf.end(), cmpPermEqual);
it != vf.end();
it = std::adjacent_find(vf.begin(), vf.end(), cmpPermEqual)) {
vf.erase(it, it + 2);
}
std::cout << "\n\nDoubles eliminated:\n";
for (const Face& f : vf) std::cout << f[0] << ' ' << f[1] << ' ' << f[2] << '\n';
return 0;
};
В конце Из функции main
вы также увидите, как мы можем исключить двойные числа. И оба. Мы сортируем вектор и затем используем std::adjacent_find
, чтобы увидеть, есть ли у нас 2 двойных, один под другим. Если так, мы стираем их обоих. Это мы повторяем до тех пор, пока больше не будет двойников.