C ++删除了vector的某些元素

时间:2014-11-26 09:52:10

标签: c++ vector multidimensional-array stl erase

我是C ++的新手,想要消除矢量元素。

我的载体就像:

<vector<vector>> objPoints;
<vector<vector>> delPoints;
<vector<vector>> objPoints2;

每个objPoints的大小为1000x3并且具有所有点数。从objPoints我想删除delPoints,即每行中的(X,Y,Z)值。

有人可以告诉我语法吗?

4 个答案:

答案 0 :(得分:2)

我将您的问题解释如下:您有两个向量objPointsdelPoints,其中包含1000个三维点。我会把它编码为

std::vector<std::array<int,3> > objPoints;

我认为你有一些光栅,你可以用int值来表示你的分数(否则,对于double条目,比较并不那么容易。)

使用std::array<int,3>的一个好处是,您可以自动获得点的词典排序(即std::lessstd::equal_to的特化,可直接使用而无需进一步使用创造一些)。


<强>算法:

首先对数组进行排序。可能有一些算法并不是必需的(请参阅@AshwaniDausodia的其他答案),但以下假定它。此外,通常通过使用排序的向量,可以获得更好的性能(至少在大O中:对于未排序的容器,它大致为O(size1*size2),而对于以下算法则较低)。排序首先需要努力O(size1 log(size1)) + O(size2 log(size2))

接下来,同时遍历两个数组,每次找到一个公共元素时,都会从其中一个向量中删除它。当您遍历排序数组时,您始终只能增加指向较小元素的迭代器,此步骤需要O(size1+size2)


<强>实施

// deletes the elements from container c1 which are also present in c2
// requires sorted containers c1 and c2
//
template< class ContainerType1, class ContainerType2 >
void delete_common_elements(ContainerType1& c1, ContainerType2 const& c2 )
{
    for(auto it1=c1.begin(), it2=c2.begin()
       ; it1!=c1.end() && it2!=c2.end(); )
    {
        if(*it1==*it2)  // eventually change here if your points are not int's
                        // but are of floating-point type
        {
             it1 = c1.erase(it1);  //it1 is increased here
        }
        else
        {
             *it1<*it2 ? ++it1 : ++it2;
        }
    }
}   

DEMO

总之,这需要O(c1.size()) + O(c1.size() * log(c1.size())的努力(自然地假设为c1.size()>=c2.size())。

可以很容易地扩展它以采用任意比较运算符而不是operator==

答案 1 :(得分:0)

如果你肯定必须使用向量,一种简单(但效率低)的方法是std::find要删除的obj要素中的元素,然后用std::vector::erase将其删除。

答案 2 :(得分:0)

一种不同的方法是:

for each point in delPoints
    if point exists in objPoints
        delete point from objPoints.

如果允许您对矢量进行排序,则可以更有效地执行此操作。我将为您提供方法和伪代码,然后您可以自己实现它。

First sort objPoints and delpoints
i=0,j=0
while i < length(objPoints) and j < length(delPoints)
    if objPoints[i] > delPoints[j]       // Means delPoints[j] is not there in objPoints. If it would have, we would have found it.
        j++
    else if objPoints[i] < delPoints[j]  // Means delPoints[j] is after objPoints[i] if it is there in objPoints
        i++
    else
        erase objPoints[i]           // Means we have found delPoints[j], so delete it.

对于comaprison,首先比较w.r.t x cordinate然后y然后z。对于排序,您可以使用std::sort与前一行中描述的相同比较功能。要删除,您可以使用std::vector::erase  或者你可以实现自己的功能。

答案 3 :(得分:0)

您可以考虑阅读this Q&A on StackOverflow on how to erase elements from STL containers

关键是使用 erase-remove idiom 来清除向量中的项目,并使用lambda来表示擦除条件:

objPoints.erase(
    std::remove_if(
        objPoints.begin(), 
        objPoints.end(), 
        [&delPoints](const Point3D& point)
        { 
            // Erasing condition:
            // Is 'point' contained in the 'delPoints' vector?
            auto it = std::find(delPoints.begin(), delPoints.end(), point);
            return (it != delPoints.end());
        }), 
    objPoints.end());

完整的可编辑代码示例(live here):

#include <algorithm>    // for std::find(), std::remove_if()
#include <array>        // for std::array
#include <iostream>     // for console output
#include <vector>       // for std::vector

typedef std::array<int, 3> Point3D;

std::ostream& operator<<(std::ostream& os, const Point3D& point)
{
    os << "{" << point[0] << ", " 
       << point[1] << ", " << point[2] << "}";

    return os;
}

std::ostream& operator<<(std::ostream& os, const std::vector<Point3D>& v) 
{
    if (v.empty())
    {
        os << "{ <empty> }" << std::endl;
        return os;
    }

    os << "{\n";
    for (const auto& point : v)
    {
        os << "  " << point << '\n';
    }
    os << "}" << std::endl;
    return os;
}

int main()
{
    std::vector<Point3D> objPoints{{1, 2, 3}, 
                                   {4, 5, 6}, 
                                   {11, 22, 33}, 
                                   {44, 55, 66}, 
                                   {77, 88, 99}};

    std::vector<Point3D> delPoints{{10, 10, 10}, 
                                   {11, 22, 33}, 
                                   {44, 55, 66}};


    std::cout << "objPoints =\n" << objPoints << std::endl;
    std::cout << "delPoints =\n" << delPoints << std::endl;

    objPoints.erase(
        std::remove_if(
            objPoints.begin(), 
            objPoints.end(), 
            [&delPoints](const Point3D& point)
            { 
                // Erasing condition:
                // Is 'point' contained in the 'delPoints' vector?
                auto it = std::find(delPoints.begin(), delPoints.end(), point);
                return (it != delPoints.end());
            }), 
        objPoints.end());

    std::cout << "\nAfter erasing, objPoints =\n";
    std::cout << objPoints << std::endl;
}

输出:

objPoints =
{
  {1, 2, 3}
  {4, 5, 6}
  {11, 22, 33}
  {44, 55, 66}
  {77, 88, 99}
}

delPoints =
{
  {10, 10, 10}
  {11, 22, 33}
  {44, 55, 66}
}


After erasing, objPoints =
{
  {1, 2, 3}
  {4, 5, 6}
  {77, 88, 99}
}