从向量列表中删除一个向量元素C++

3

我一直在论坛和其他地方寻找解决这个问题的方法,但唯一找到的结果是关于遍历列表或访问向量列表中元素的。所以我想访问一个向量的erase()函数。但我需要在包含向量的列表容器中完成它。下面是一个示例代码,应该有助于说明。

#include<vector>
#include<list>
#include<iostream>

using namespace std;

int main()
{
    vector <int> a1 = { 1, 1, 1, 1, 1 };
    vector <int> a2 = { 2, 2, 2, 2, 2 };
    vector <int> a3 = { 3, 3, 3, 3, 3 };

    list<vector<int>> listVec;

    listVec.push_back(a1);
    listVec.push_back(a2);
    listVec.push_back(a3);

    for (auto p : listVec){

        for (auto p1 : p){
            cout << p1;
        }
        cout << "\n";
    }


}

那么,从包含在列表中的向量a2中删除一个元素的最简单方法是什么?现在我甚至没有错误版本。这段代码应该在遍历循环中的某个位置,但我无法编写它。

谢谢


阅读 http://en.cppreference.com/w/cpp/container/vector/erase - PiotrNycz
以及 http://en.cppreference.com/w/cpp/concept/BidirectionalIterator - PiotrNycz
和http://en.cppreference.com/w/cpp/container/list/begin - PiotrNycz
我知道如何使用erase(),但当我想从一个向量列表中删除元素时,我找不到访问它的方法。 - fredric
2个回答

3

好的,标准的做法:

auto iter = listVec.begin();
std::advance(iter, 1); // get second element
iter->erase(iter->begin() + n); // erase nth element of second element of list

在您的for循环中,需要迭代元素的引用而不是迭代元素的副本,否则您只能从向量的副本中删除元素:

int pos = 0;
for (auto& p : listVec){
//       ^
   if (++pos == 1)
   {
       p.erase(p.begin() + n); // erase nth element of second element of list
   }
}

参考文献列表:


额外答案:

对于您在评论中提到的问题 - 您拥有容器Document和指向Document的迭代器 - 如Text_iterator - 最好遵循STL方案 - 因此将erase函数添加到Document中并使该类成为Text_iterator的友元,请参见:

class Text_iterator {   // keep track of line and character position within            a line
    list<Line>::iterator ln;
    Line::iterator pos;
    friend class Document; 

并且:

struct Document {
    list<Line> line;            //doucument is a list of lines
    void erase(Text_iterator iter)
    {
        iter.ln->erase(iter.pos);
    }

有没有不使用advance()的方法来实现呢?最好的情况是我只需输入正确元素的迭代器,就可以将其删除。是否有这样的选项? - fredric
@fredric 列表迭代器不是随机访问迭代器,因此不可能 - 请参见 en.cppreference.com/w/cpp/concept/BidirectionalIterator。但是您可以拥有向量的向量,而不是向量的列表... - PiotrNycz
@fredric 嗯,有一个统一容器擦除的提案。所以很快,你就可以使用 任何类型的容器 来说 std::erase(listVec, "bad word") 或者 std::erase_if(listVec, [](auto x) -> { return f(x); }) 了!非常棒,但是我们要等到 C++17 才能看到它 :) - Brian Rodriguez
你发布的代码有效并回答了一个问题。 但我之所以问这个问题是因为我想处理早期的程序,我仍然无法解决其中的问题。早期的帖子http://stackoverflow.com/questions/33572031/getting-basic-text-processor-in-c-to-compile 指出了文本处理程序的问题。 我找不到使用自定义迭代器从字符向量列表中遍历的Document类中删除单词的方法。我尝试先编写一个删除一个字符的函数,但卡住了。 - fredric
感谢您对Text_iterator问题的回复。 我尝试在结构体内定义函数,但出现了以下编译错误: 错误2 错误C2232:'->Text_iterator :: ln':左操作数具有'class'类型,请使用'。' 错误4 错误C2232:'->Text_iterator :: pos':左操作数具有'class'类型,请使用'。' 错误1 错误C2819:类型'Text_iterator'没有重载成员'operator->'是否需要重载访问运算符?尝试获取一些示例,但似乎非常特定。还有其他方法吗? - fredric
@fredric 不用加 operator -> - 那是我的错,我非常确定这个实现所以没有测试/编译它。请看更新 - 这次我检查了它是否能够与你在另一个问题中的示例一起工作。 - PiotrNycz

1
迭代
for (auto p : listVec){

在迭代列表时,它会复制列表中每个向量。因此,虽然您可以调用p.erase来删除该向量的元素,但这只会影响副本p,而不是列表中的向量。

如果您改为

for (auto &p : listVec){

p现在将是列表中每个向量的引用。因此,如果您调用p.erase,那么将影响列表中的向量。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接