从std::vector中查找std::map中的对象

finding objects in std::map from std::vector

本文关键字:std 对象 map 查找 vector      更新时间:2023-10-16

给各位c++专家一个快速的问题:

在我正在做的项目中,有一个类包含指向vector对象的指针:

    std::vector<object*> objects;

并且有一个结构体可以为对象添加偏移量(Point2D显然是x,y坐标)

    struct DraggedObject{
    object* obj;
    Point2D offset;
    DraggedObject():obj(NULL),offset(Point2D(0,0)){}
};

当你拖动一个对象时它会将它添加到std::map中,就像这样:

    std::map <int, DraggedObject> dragged_objects;

所以我的问题是:有一个循环,我需要移动这个对象,但跳过拖动的对象。我的问题是:是否有一种方法可以循环遍历对象向量并找出对象是否在dragged_object映射上?

我正在做这样的事情:

for(std::vector<object*>::iterator it = objects.begin(); it != objects.end(); it++){
    if(//Object is not in dragged_objects){
        (*it)->move_to( Point2D( //Some point);
    }else{
        (*it)->move_to (Point2D (//Point of dragged object);
}

但是我不知道如何做这个比较…

std::map优化为按键(在本例中为int值)快速查找,而不是按值(您的对象*)快速查找。所以你唯一的办法就是迭代整个地图,直到找到它。当映射很小且代码段对性能不重要时,可以这样做。当性能问题时,您可以添加一个额外的std::set并存储当前正在被拖动的所有对象,或者您可以让对象本身知道它们是否正在被拖动,并在您的对象类中添加一个isDragged()方法。

我相信您可以使用set_difference。你将不得不实现自定义比较器,而且你将不得不对向量中的元素排序。除非您这样做,否则我认为您只能对vector中的每个元素执行查找,以验证它是否存在于映射中。

如果可能的话,用object*键收集容器(map)中的拖动对象,例如std::map <object*, DraggedObject>而不是std::map <int, DraggedObject>。然后你可以这样写你的if:

 if(dragged_objects.count(*it)){
        (*it)->move_to( Point2D( //Some point);
    }else{
        (*it)->move_to (Point2D (//Point of dragged object);

您可以改变您的方法并迭代您的拖动对象映射,在每个拖动对象上完成您需要完成的工作,然后将对象添加到临时std::vector<object*>。当循环结束时,你可以遍历vector,只对不在临时vector中的元素做一些操作。

您可以使用的一种方法是将vector替换为一个列表,并使该列表仅包含未封装的对象。

然后遍历该列表。如果需要所有对象,则需要遍历illist和map。不确定这样做的顺序有多重要,但如果对象的id很重要(您存储在map中),您可以根据map中的id在列表和map中迭代"合并"。

在这种情况下,列表比向量更好的原因是,如果你要从集合的中间拖动对象,从列表中删除是常数时间。

既然您说对象ID是它们在dragged_objects map中的键,那么您可以使用find map方法。我认为应该是这样的。

std::map::iterator miter;
for (auto &obj : objects)
{
    miter = dragged_objects.find(obj.id);
    if (miter != dragged_objects.end()) {
        /* do for non-dragged objects */
    } else {
        /* do for dragged objects */
    }
}

根据需要调整非c++ 11编译器

用于索引的int从何而来地图吗?如果它是从object中提取的标识符,那么所有你要做的就是在循环中提取它,看看它是不是显示在地图上(使用map::find)。否则,你会要么需要一个额外的映射,用object*索引,要么需要遍历所有的dragged_objects,看看看看它是否有你想要的地址(std::find_if)。根据dragged_objects的数量,这可能是缓慢;但通常情况下,我猜dragged_objects是两者之一为空或只有一个条目。如果是这样的话,每次循环的线性搜索都是完美的可以接受的。