[英]Elegant way to find if a class instance is contained in a std::vector (C++)
I want to construct a vector that will hold int M
elements of my class Point
which represent a single point (x,y) where both x,y are int
.我想构造一个向量来保存我的 class
Point
的int M
个元素,这些元素代表一个点 (x,y),其中 x,y 都是int
。
The points that will be stored in this vector are randomly generated.将存储在此向量中的点是随机生成的。 However, I do not want to store the same point more than once.
但是,我不想多次存储同一点。
My implementation is the following:我的实现如下:
#include <algorithm>
#include <random>
std::random_device rd;
std::mt19937 mt(rd());
std::vector<Point> InitList(int M)
{
if ( M <=0 )
{
std::cout << "InitList: Length of vector must be greater than zero. Don't play around!"
<< std::endl;
exit(EXIT_FAILURE);
}
Point to_erase(-100,-100); // <----- can I get rid of this?
Point to_add;
int x,y;
std::vector<Point> vec = {};
vec.push_back(to_erase); // <----- and this
while (vec.size() < M+1) // <----- and then M+1 -> M
{
std::uniform_int_distribution<int> RandInt(0,100);
x = RandInt(mt);
y = RandInt(mt);
point.set(x,y);
if ( std::find(vec.begin(), vec.end(),to_add) == vec.end() )
vec.push_back(to_add);
}
vec.erase (vec.begin()); // <----- and finally avoid this?
return vec;
}
How can I avoid the trick of adding the first instance to_erase
?如何避免添加第一个实例
to_erase
的技巧?
EDIT编辑
So I changed the implementation to use std::unordered_set
and I am getting the following errors:因此,我将实现更改为使用
std::unordered_set
,但出现以下错误:
error: use of deleted function ‘std::unordered_set<_Value, _Hash, _Pred, _Alloc>::unordered_set() [with _Value = Site; _Hash = std::hash<Site>; _Pred = std::equal_to<Site>; _Alloc = std::allocator<Site>]’
note: ‘std::hash<Site>::hash()’ is implicitly deleted because the default definition would be ill-formed:
101 | struct hash : __hash_enum<_Tp>
| ^~~~
/usr/include/c++/9/bits/functional_hash.h:101:12: error: no matching function for call to ‘std::__hash_enum<Site, false>::__hash_enum()’
/usr/include/c++/9/bits/functional_hash.h:82:7: note: candidate: ‘std::__hash_enum<_Tp, <anonymous> >::__hash_enum(std::__hash_enum<_Tp, <anonymous> >&&) [with _Tp = Site; bool <anonymous> = false]’
82 | __hash_enum(__hash_enum&&);
| ^~~~~~~~~~~
And the list goes on.而这样的例子不胜枚举。 I guess there is an implementation missing in my class
Point
.我猜我的 class
Point
中缺少一个实现。 What should I do?我应该怎么办?
You can guarantee uniqueness just by using std::set
( https://www.cplusplus.com/reference/set/set/ ) instead of std::vector
.您可以通过使用
std::set
( https://www.cplusplus.com/reference/set/set/ ) 而不是std::vector
来保证唯一性。
If order doesn't matter, use std::unordered_set
.如果顺序无关紧要,请使用
std::unordered_set
。
Regarding the hash
issues you're seeing -- you have to define a hash function for a custom type, when using a few C++ types like set
, unordered_set
, map
, etc. This is a function that returns a unique number based on the value of your custom Point
instance. Regarding the
hash
issues you're seeing -- you have to define a hash function for a custom type, when using a few C++ types like set
, unordered_set
, map
, etc. This is a function that returns a unique number based on the value您的自定义Point
实例。 I stubbed out this example to give you an idea of how this might work for you, but YMMV:我删除了这个例子,让你了解这对你来说是如何工作的,但是 YMMV:
#include <iostream>
#include <unordered_set>
struct Point
{
int x;
int y;
Point(int x, int y): x(x), y(y) {};
};
bool operator==(const Point& lhs, const Point& rhs)
{
return ((lhs.x == rhs.x) and (lhs.y == rhs.y));
}
namespace std
{
template <>
struct hash<Point>
{
size_t operator()( const Point& p ) const
{
return (p.x << 32 | p.y);
}
};
}
int main() {
Point p1(3,2);
Point p2(3,2);
std::unordered_set<Point> someSet;
someSet.insert(p1);
std::cout << "set size:" << someSet.size() << std::endl;
// set size: 1
someSet.insert(p2);
std::cout << "set size:" << someSet.size() << std::endl;
// set size: 1 (still!)
return 0;
}
If only presence is relevant: std::set
.如果只有存在是相关的:
std::set
。
If you need also occurrence count, you could use std::map<Point, int>
, where the int
is the count.如果您还需要出现计数,则可以使用
std::map<Point, int>
,其中int
是计数。 With some special handling to remove elements when counts gets to zero.当计数为零时,通过一些特殊处理来删除元素。
You could replace std::map
with std::unordered_map
for performance reasons.出于性能原因,您可以将
std::map
替换为std::unordered_map
。 But ALWAYS test both before deciding.但总是在决定之前测试两者。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.