C++ 查找向量中恰好重复一次的值
我有一个四面体网格作为点向量(C++ 查找向量中恰好重复一次的值,c++,containers,unique,C++,Containers,Unique,我有一个四面体网格作为点向量(std::array)和一个四面体向量(std::array)。我想检查特定顶点是否属于网格的边界 为此,每个四面体定义了4个面([0,1,2]、[0,1,3]、[1,2,3]和[0,2,3])。面[0,1,2]被认为与面[0,2,1]或任何其他置换相等。如果面在所有网格中只存在一次,则面是边界。内部面显示两次。如果顶点属于边界面,则它是边界 我的计划是创建所有面的向量(std::array),然后删除出现两次的条目。如果两个条目出现两次,我想删除它们,而不仅仅是重
std::array
)和一个四面体向量(std::array
)。我想检查特定顶点是否属于网格的边界
为此,每个四面体定义了4个面([0,1,2]、[0,1,3]、[1,2,3]和[0,2,3])。面[0,1,2]被认为与面[0,2,1]或任何其他置换相等。如果面在所有网格中只存在一次,则面是边界。内部面显示两次。如果顶点属于边界面,则它是边界
我的计划是创建所有面的向量(std::array
),然后删除出现两次的条目。如果两个条目出现两次,我想删除它们,而不仅仅是重复的条目。此外,相等比较器必须能够检测两个面是否相等,同时考虑到可能的排列
我不知道如何继续进行,或者如果存储一个包含所有面的向量,然后删除元素是最好的解决方案。任何想法都会很有帮助 归根结底,创建比较函数,将容器中的值的排列视为相等 这样做的概念是:
- 将容器中的值复制到
std::vector
- 然后对
s进行排序std::vector
- 然后使用
std::vector
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;
};
在函数
main
的末尾,您还将看到如何消除双精度。而且,他们两个。我们对向量进行排序,然后使用std::nextant_find
,查看是否有两个双精度,一个在另一个之下。如果是这样的话,我们会把它们都抹掉。我们重复这个过程,直到不再有双精度。您能更改点向量中值的顺序吗?如果你能做到这一点,那么你就不需要处理排列了。事实上,我可以。这将避免使用自定义比较器cmpPermLess和cmpPermEqual要检测的是两个置换是否相等,对吗?我本来打算用is_置换。因为你对两个面(数组)重载运算符<,我必须注意不要比较其他有其他不同含义的数组,对吗?是的,你是对的。这种方法消除了排列。它将两个排列视为相等。是的,同样正确,你需要比较“苹果与苹果”实际上,没有这个代码就有问题了。它适用于我的情况,我最多只有2个元素,但对于3个或更多偶数元素,它将失败。你能为文档目的更新它吗?
#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;
};