关于c ++:如何从具有特定值的stl向量中删除项?

关于c ++:如何从具有特定值的stl向量中删除项?

How do I remove an item from a stl vector with a certain value?

我查看了stl vector的API文档,发现vector类上没有允许删除具有特定值的元素的方法。这似乎是一个常见的操作,而且似乎奇怪的是,没有内置的方法来完成这项操作。


std::remove实际上不会从容器中删除元素,但它会返回新的end迭代器,该迭代器可以传递给container_type::erase来真正删除容器末尾的多余元素:

1
2
3
4
std::vector<int> vec;
// .. put in some values ..
int int_to_remove = n;
vec.erase(std::remove(vec.begin(), vec.end(), int_to_remove), vec.end());

如果您想删除一个项目,下面的操作会更有效。

1
2
3
4
5
6
std::vector<int> v;


auto it = std::find(v.begin(), v.end(), 5);
if(it != v.end())
    v.erase(it);

或者,如果订单对您不重要,您可以避免移动项目的开销:

1
2
3
4
5
6
7
8
9
10
11
12
13
std::vector<int> v;

auto it = std::find(v.begin(), v.end(), 5);

if (it != v.end()) {
  using std::swap;

  // swap the one to be removed with the last element
  // and remove the item at the end of the container
  // to prevent moving all items after '5' by one
  swap(*it, v.back());
  v.pop_back();
}


使用全局方法std::remove和begin和end迭代器,然后使用std::vector.erase实际删除元素。

文档链接标准::删除http://www.cppreference.com/cppalgorithm/remove.html标准::vector.erase http://www.cppreference.com/cppvector/erase.html

1
2
3
4
5
6
7
8
9
10
11
12
13
std::vector<int> v;
v.push_back(1);
v.push_back(2);

//Vector should contain the elements 1, 2

//Find new end iterator
std::vector<int>::iterator newEnd = std::remove(v.begin(), v.end(), 1);

//Erase the"removed" elements.
v.erase(newEnd, v.end());

//Vector should now only contain 2

感谢吉姆·巴克指出了我的错误。


其他的答案包括如何做好这件事,但我想我也会指出,这并不奇怪,这不在向量API中:它效率低下,通过向量线性搜索值,然后进行大量复制以删除它。

如果您正在集中执行此操作,那么出于这个原因考虑使用std::set是值得的。


如果您有一个未排序的向量,那么您可以简单地与最后一个向量元素交换,然后与resize()交换。

有了订好的集装箱,你最好还是带上?std::vector::erase()。注意,在中定义了一个std::remove(),但实际上并没有进行擦除。(仔细阅读文档)。


较短的解决方案(不强制您重复向量名4次)是使用boost:

1
2
3
4
5
#include <boost/range/algorithm_ext/erase.hpp>

// ...

boost::remove_erase(vec, int_to_remove);

请参阅http://www.boost.org/doc/libs/1_64_0/libs/range/doc/html/range/reference/algorithms/new/remove_erase.html


另请参阅std::remove_if to be able to use a predicate…

下面是上面链接中的示例:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
vector<int> V;
V.push_back(1);
V.push_back(4);
V.push_back(2);
V.push_back(8);
V.push_back(5);
V.push_back(7);

copy(V.begin(), V.end(), ostream_iterator<int>(cout,""));
    // The output is"1 4 2 8 5 7"

vector<int>::iterator new_end =
    remove_if(V.begin(), V.end(),
              compose1(bind2nd(equal_to<int>(), 0),
                       bind2nd(modulus<int>(), 2)));
V.erase(new_end, V.end()); [1]

copy(V.begin(), V.end(), ostream_iterator<int>(cout,""));
    // The output is"1 5 7".

来自C++ 20:

一个非成员函数引入了std::erase,它将要删除的向量和值作为输入。

前任:

1
2
std::vector<int> v = {90,80,70,60,50};
std::erase(v,50);

有两种方法可以用来特别删除项目。让我们取一个向量

1
2
3
4
5
6
7
std :: vector < int > v;
v.push_back(10);
v.push_back(20);
v.push_back(30);
v.push_back(40);
v.push_back(40);
v.push_back(50);

1)非有效方式:虽然看起来效率很高,但不是因为擦除函数删除了元素并将所有元素向左移动1。所以它的复杂性是O(n^2)

1
2
3
4
5
6
7
8
9
10
11
std :: vector < int > :: iterator itr = v.begin();
int value = 40;
while ( itr != v.end() )
{
   if(*itr == value)
   {
      v.erase(itr);
   }
   else
       ++itr;
}

2)有效方法(推荐):也称为擦除-删除习语。

  • 移除将给定范围转换为一个范围,所有与给定元素比较的元素都移到容器的开头。
  • 所以,实际上不要删除匹配的元素。它只是将不匹配的转移到starting,并将迭代器赋给新的有效end。它只需要O(N)复杂性。

删除算法的输出是:

1
10 20 30 50 40 50

因为REMOVE的返回类型是该范围的新结尾的迭代器。

1
2
template <class ForwardIterator, class T>
  ForwardIterator remove (ForwardIterator first, ForwardIterator last, const T& val);

现在使用vector的erase函数删除从新的元素到旧的元素。它需要O(1)次。

1
v.erase ( std :: remove (v.begin() , v.end() , element ) , v.end () );

所以这个方法在O(n)中有效


如果你不想做任何额外的包括:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
vector<IComponent*> myComponents; //assume it has items in it already.
void RemoveComponent(IComponent* componentToRemove)
{
    IComponent* juggler;

    if (componentToRemove != NULL)
    {
        for (int currComponentIndex = 0; currComponentIndex < myComponents.size(); currComponentIndex++)
        {
            if (componentToRemove == myComponents[currComponentIndex])
            {
                //Since we don't care about order, swap with the last element, then delete it.
                juggler = myComponents[currComponentIndex];
                myComponents[currComponentIndex] = myComponents[myComponents.size() - 1];
                myComponents[myComponents.size() - 1] = juggler;

                //Remove it from memory and let the vector know too.
                myComponents.pop_back();
                delete juggler;
            }
        }
    }
}


推荐阅读

    linux运维操作命令?

    linux运维操作命令?,系统,网络,基础,标准,工具,信息,工作,命令,软件,数据,lin

    linux默认命令删除?

    linux默认命令删除?,系统,软件,名称,档案,命令,文件,目录,不了,电脑,文件夹,

    linux清空操作命令?

    linux清空操作命令?,系统,数据,命令,名称,不了,文件夹,文件,环境,回收站,目

    linux命令发现不了?

    linux命令发现不了?,软件,系统,发行,工具,名称,不了,命令,地方,代理,信息,lin

    linux安装操作命令?

    linux安装操作命令?,系统,工作,地址,工具,服务,情况,信息,命令,最新,管理,lin

    linux删除空行命令?

    linux删除空行命令?,名称,不了,命令,文件夹,文件,时间,工作,简介,情况,资料,l

    linux删除软件命令?

    linux删除软件命令?,软件,系统,命令,不了,名称,数据,文件夹,文件,工具,百度,l

    linux删除集群命令?

    linux删除集群命令?,软件,管理,工具,平台,工作,系统,技术,数据,公司,产品,在l

    linux操作系mv命令?

    linux操作系mv命令?,名字,系统,软件,文件,命令,信息,地址,目录,文件夹,源文

    linux输入命令删除键?

    linux输入命令删除键?,名称,系统,档案,命令,文件,目录,不了,数据,文件夹,终

    linux操作命令大全图?

    linux操作命令大全图?,工作,地址,系统,信息,命令,目录,控制台,功能,操作,内

    linux删除群组的命令?

    linux删除群组的命令?,系统,管理,工作,名称,命令,地址,邮箱,基础,密码,用户

    删除密码命令linux?

    删除密码命令linux?,密码,系统,管理,电脑,软件,百度,信息,名称,名字,命令,lin

    linux恢复删除命令?

    linux恢复删除命令?,工具,系统,信息,文件,命令,数据,软件,名称,不了,目录,lin

    linux的删除文件命令?

    linux的删除文件命令?,名称,不了,系统,文件夹,命令,文件,环境,档案,目录,指

    linux操作命令论文?

    linux操作命令论文?,管理,系统,设计,网络,企业,基础,机电设备,技术,发展,机

    linux删除容器命令?

    linux删除容器命令?,系统,名称,不了,档案,命令,文件夹,文件,环境,目录,指令,l

    linux中vi命令删除?

    linux中vi命令删除?,系统,数字,命令,环境,标的,数据,不了,名称,连续,位置,Lin

    linux服务器删除命令?

    linux服务器删除命令?,系统,服务,管理,情况,命令,工作,互动,地址,软件,较大,l

    linux删除命令大全?

    linux删除命令大全?,软件,系统,名称,命令,通用,档案,不了,电脑,文件夹,文件,