【问题标题】:C++: how to understand iterators and remove elements from a vectorC++:如何理解迭代器并从向量中删除元素
【发布时间】:2013-01-07 15:05:08
【问题描述】:

我有两个向量。 “点”是我原来的点数组。 “Chosen”是要从“Points”中删除的点的集合。我想从“选择”中获取唯一的点 ID,将它们分配给迭代器并删除这些点。但不知怎的,我做不到。

其次,在我研究的示例中,我无法理解迭代器如何链接到确定的向量。希望在您的帮助下,我会理解迭代器。

#include <StdAfx.h>
#include <iostream>
#include <vector>
#include <algorithm>
#include <iterator>

using namespace std;
struct SPoint
{
    int id;
    int X;
    int Y;
};

vector<SPoint> points;
vector<SPoint> chosen;
vector<SPoint> cleared;

vector<SPoint>::iterator it;

void print_vect(const vector<SPoint> & vect)
{
    for (int i = 0; i < vect.size(); ++i)
    {
        cout << vect[i].id << " (" << vect[i].X << "," << vect[i].Y << ")"<<endl;               
    }           

    cout << endl;   
}
bool compare(double val1, double val2)
{
    return val1 > val2;
}
void sort_points(vector<SPoint> & vect, char command)
{
    bool cmp_result;
    SPoint temp;
    bool sorted=true;
    for (int i = 0; i < vect.size()-1 ; i++)
    {
        sorted=true;
        for (int j = 1; j <= vect.size()-1; j++)
        {
            switch (command) 
            {
                case 'x': 
                    {
                        cmp_result = compare(vect[j-1].X, vect[j].X); 
                        break;
                    }
                case 'y': 
                    {
                        cmp_result = compare(vect[j-1].Y, vect[j].Y); 
                        break;              
                    }               
                case 'i': 
                    {
                        cmp_result = compare(vect[j-1].id, vect[j].id); 
                        break;              
                    }           
            }

            if (cmp_result)
            {
                sorted = false;
                temp = vect[j-1];
                vect[j-1] = vect[j];
                vect[j] = temp;
            }

        }
        if (sorted) 
        {
            cout << "Sorted:" << endl;
            print_vect(vect);           
            break;
        }
    }
}

int _tmain(int argc, _TCHAR* argv[])
{
    SPoint temp;
    for (int i = 0; i < 10; i++)
    {
        temp.id = i;
        temp.X = i;
        temp.Y = i;
        points.push_back(temp);
    }

    for (int i = 5; i < 10; i++)
    {
        temp.id = i;
        temp.X = i;
        temp.Y = i;
        chosen.push_back(temp);
    }

    cout << "Points:" << endl;
    print_vect(points);
    cout << endl << endl;

    cout << "Chosen:" << endl;
    print_vect(chosen);

    system("pause");

    vector<SPoint>::iterator it;
    for (int i = 0;i < chosen.size(); i++)
    {       
        //points.erase(it);
    }   

    print_vect(points);
    system("pause");


    print_vect(cleared);
    system("pause");
    return 0;
}

【问题讨论】:

  • somehow I can't do it 是什么意思,错误是什么,您为重现它而编写的 minimal 代码在哪里?
  • 我不认为迭代器是正确的方法。迭代器用于“迭代”集合并做一些事情。我认为它会比使用 vector[i] 在你的向量中移动更快。
  • 好吧,它就在那里 vector::iterator it;对于 (int i = 0;i
  • // 擦除前 3 个元素:myvector.erase (myvector.begin(),myvector.begin()+3);因此,如果您想删除向量中的某些值,只需将整数传递给 erase() 以进行特定删除,使用 for (vector&lt;SPoint&gt;::iterator it = chosen.begin(); it != chosen.end(); ++it) 之类的东西,比较 *it 中的值,然后做一些事情
  • 我喜欢你如何使用“做事”而不考虑可能的影响,@Zaiborg

标签: c++


【解决方案1】:

一般来说,修改被迭代的容器是个坏主意。另请注意,如果Chosen 未排序,它将在O(Points.size() * Chosen.size()) 中工作(+重新分配);除了将 Points 中的每个元素与 Chosen 中的每个元素(直到找到或结束)进行比较之外,别无他法。因此,最好使用set(或者,甚至更好,unordered_set)作为Chosen 的容器。另请注意,如果您想从 Points 中间删除元素,则必须进行 大量 重新分配,同样,setlist 会更好想法。

您可以将额外的谓词传递给std::sort 以按对象的特定字段排序 - 您不必自己重新实现排序算法。

要检查向量是否已排序,您可以使用is_sorted 方法(或者,如果您使用的是旧编译器,则使用adjacent_find,如here)。

【讨论】:

  • 不,想法不是那样的。看:id 是唯一的。然后我们可以遍历“chosen”,只取id,从“points”中移除具有相同id的元素。没有通过我们正在修改的向量进行迭代。
  • 呃,你如何在不迭代的情况下“从点中删除具有相同 id 的元素”?
  • 如果您将迭代器传递给points.erase按照问题中的要求,根据定义,您就是在迭代。这就是获取 iterator 的方式。
  • Bartek,vector 似乎是一个 linced 列表。我想可以从这样的列表中删除一个元素。
  • @Kifsif 你所说的完全不真实。 std::vector 是一个连续的内存阵列。我建议你先买一本关于 C++ 标准库的书。
【解决方案2】:

我要建议一个重大的改变:不要在这里使用std::vector,而是使用std::map,使用点的id作为键和X/Y坐标作为值:

using namespace std;
struct SPoint
{
    int X;
    int Y;
};

map<int, SPoint> points;
vector<int> chosen; // only keeps chosen id's, not complete points

void print_points(const map<int, SPoint> & points)
{
    for (map<int, SPoint>::const_iterator i = points.begin(); i != points.end(); ++i)
    {
        cout << i->first << " (" << i->second.X << "," << i->second.Y << ")"<<endl;               
    }           

    cout << endl;   
}

int tmain(int argc, char* argv[])
{
    SPoint temp;
    for (int i = 0; i < 10; i++)
    {
        temp.X = i;
        temp.Y = i;
        points[i] = temp;
    }

    for (int i = 5; i < 10; i++)
    {
        chosen.push_back(i);
    }

    cout << "Points:" << endl;
    print_points(points);
    cout << endl << endl;

    system("pause");

    for (vector<int>::iterator it = chosen.begin(); it != chosen.end(); it++)
    {       
        points.erase(*it); // erase all points with id corresponding to the current value of chosen
    }   

    print_points(points);
    system("pause");
    return 0;
}

【讨论】:

    猜你喜欢
    • 2014-09-04
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-07-02
    • 2015-04-21
    • 1970-01-01
    • 1970-01-01
    • 2017-10-24
    相关资源
    最近更新 更多