它是在所有可能从一个向量与C + + 11的for循环删除? [英] Is it at all possible to erase from a vector with C++11's for loops?

查看:207
本文介绍了它是在所有可能从一个向量与C + + 11的for循环删除?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

好的。为了其他(更简单,但不足够解释)的问题,这可能看起来,我不是问这是可能还是不可能(因为我已经发现了),我问,如果有一个更轻的替代我问题。



我有什么将被认为是一个主类,在那个主类中,有一个变量引用一个世界地图类。本质上,这个WorldMap类是其他类变量的容器。主类执行所有循环并更新所有相应的活动对象。在这个循环中有一些时候,我需要删除一个向量的一个对象,它是一个递归的容器集合(如提供的代码所示)。这将是非常繁琐的反复必须引用必要的变量作为指针指向另一个指针(等等)指向我需要的特定对象,并稍后擦除它(这是我在切换到C ++之前使用的概念11)所以我有一个范围for循环(也显示在代码)。我的示例代码显示了我的想法,我已经到位,在那里我想减少thedium,以及使代码更容易阅读。



这是示例代码:

  struct item {
int stat;
};

结构字符{
int otherStat;
std :: vector< item> myItems;
};

struct charContainer {
std :: map< int,character> myChars;
};

int main(){
// ...
charContainer box;
//我想做更接近这个
的东西(item targItem:box.myChars [iter] .myItems){
//然后我只需要使用targItem作为引用
if(targItem.isFinished)
box.myChars [iter] .myItems.erase(targItem);
}
//而不是这样做
for(int a = 0; a< box.myChars [iter] .myItems.size(); a ++){
//然后我必须重复使用box.myChars [iter] .myItems [a]
if(box.myChars [iter] .myItems [a] .isFinished)
box.myChars [iter] .myItems。 erase(box.myChars [iter] .myItems [a]);
}
}

TLDR:我想删除重复呼叫通过使用C ++ 11中显示的循环的新范围完全引用。



EDIT :我不是试图删除所有元素立刻。我想问我如何在第一个循环的问题中删除它们。我删除它们,当我与外部完成(通过if语句)。如何删除特定的元素,而不是所有的?

解决方案

如果你只想清除一个std :: vector是一个非常简单的方法,您可以使用:

  std :: vector< item& v; 

//用元素填充v ...

v.clear(); //从v中删除所有元素

除此之外,我想指出, [1]删除向量中的元素需要使用迭代器,并且[2]即使你的方法被允许,如果你不小心,从一个for循环中的向量中擦除元素是一个坏主意。假设你的向量有5个元素:

  std :: vector< int& v = {1,2,3,4,5}; 

然后你的循环会有以下效果:




  • 第一次迭代: a == 0,size()== 5 。我们删除第一个元素,然后向量将包含 {2,3,4,5}


  • 第二次迭代: a == 1,size()== 4 。然后,我们删除元素,向量将包含 {2,4,5}


  • 第三次迭代: a == 2,size()== 3 。我们删除了第三个​​元素,我们留下了最终结果 {2,4}




因为这实际上并没有清空向量,我想这不是你要找的。

如果你有一些特定的条件,你想要应用于删除元素,它很容易应用在C ++ 11中以下面的方式:

  std :: vector< MyType> v = {/ * initialize vector * /}; 

//以下是一个lambda,它是一个可以存储在变量中的函数。
//这里我们使用它来表示应该用于从向量v中删除
//元素的条件
auto isToRemove = [](const MyType& value){
return / * true如果删除,false如果不是* /
};

//向量可以使用方法erase()同时删除多个元素。
// Erase将删除指定范围内的所有元素。我们使用这个方法
//和标准库提供的另一个方法:remove_if。
//它所做的是删除一个特定谓词
//在一个范围内返回true的所有元素,并在结尾留下空格。
v.erase(std :: remove_if(std :: begin(v),std :: end(v),isToRemove),std :: end(v));

//完成!


Alright. For the sake of other (more simple but not explanatory enough) questions that this might look like, I am not asking if this is possible or impossible (because I found that out already), I am asking if there is a lighter alternative to my question.

What I have is what would be considered a main class, and in that main class, there is a variable that references to a 'World Map' class. In essence, this 'WorldMap' class is a container of other class variables. The main class does all of the looping and updates all of the respective objects that are active. There are times in this loop that I need to delete an object of a vector that is deep inside a recursive set of containers (As shown in the code provided). It would be extremely tedious to repeatedly have to reference the necessary variable as a pointer to another pointer (and so on) to point to the specific object I need, and later erase it (this was the concept I used before switching to C++11) so instead I have a range for loop (also shown in the code). My example code shows the idea that I have in place, where I want to cut down on the tedium as well as make the code a lot more readable.

This is the example code:

struct item{
    int stat;
};

struct character{
    int otherStat;
    std::vector<item> myItems;
};

struct charContainer{
    std::map<int, character> myChars;
};

int main(){
    //...
    charContainer box;
    //I want to do something closer to this
    for(item targItem: box.myChars[iter].myItems){
        //Then I only have to use targItem as the reference
        if(targItem.isFinished)
            box.myChars[iter].myItems.erase(targItem);
    }
    //Instead of doing this
    for(int a=0;a<box.myChars[iter].myItems.size();a++){
        //Then I have to repeatedly use box.myChars[iter].myItems[a]
        if(box.myChars[iter].myItems[a].isFinished)
            box.myChars[iter].myItems.erase(box.myChars[iter].myItems[a]);
    }
}

TLDR: I want to remove the tedium of repeatedly calling the full reference by using the new range for loops shown in C++11.

EDIT: I am not trying to delete the elements all at once. I am asking how I would delete them in the matter of the first loop. I am deleting them when I am done with them externally (via an if statement). How would I delete specific elements, NOT all of them?

解决方案

If you simply want to clear an std::vector, there is a very simple method you can use:

std::vector<item> v;

// Fill v with elements...

v.clear(); // Removes all elements from v.

In addition to this, I'd like to point out that [1] to erase an element in a vector requires the usage of iterators, and [2] even if your approach was allowed, erasing elements from a vector inside a for loop is a bad idea if you are not careful. Suppose your vector has 5 elements:

std::vector<int> v = { 1, 2, 3, 4, 5 };

Then your loop would have the following effect:

  • First iteration: a == 0, size() == 5. We remove the first element, then the vector will contain {2, 3, 4, 5}

  • Second iteration: a == 1, size() == 4. We then remove the second element, then the vector will contain {2,4,5}

  • Third iteration: a == 2, size() == 3. We remove the third element, and we are left with the final result {2,4}.

Since this does not actually empty the vector, I suppose it is not what you were looking for.

If instead you have some particular condition that you want to apply to remove the elements, it is very easily applied in C++11 in the following way:

std::vector<MyType> v = { /* initialize vector */ };

// The following is a lambda, which is a function you can store in a variable.
// Here we use it to represent the condition that should be used to remove
// elements from the vector v.
auto isToRemove = [](const MyType & value){ 
    return /* true if to remove, false if not */ 
};

// A vector can remove multiple elements at the same time using its method erase().
// Erase will remove all elements within a specified range. We use this method 
// together with another method provided by the standard library: remove_if.
// What it does is it deletes all elements for which a particular predicate 
// returns true within a range, and leaves the empty spaces at the end.
v.erase( std::remove_if( std::begin(v), std::end(v), isToRemove ), std::end(v) );

// Done!

这篇关于它是在所有可能从一个向量与C + + 11的for循环删除?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆