繁体   English   中英

从std :: vector删除项目的任意列表 <std::vector<T> &gt;

[英]remove arbitrary list of items from std::vector<std::vector<T> >

我有一个向量,代表一个数组。 我想高效地删除行,即以最小的复杂度和分配量

我曾考虑过使用移动语义构建一个新的向量向量,仅复制未删除的行,如下所示:

    //std::vector<std::vector<T> > values is the array to remove rows from
    //std::vector<bool> toBeDeleted contains "marked for deletion" flags for each row

    //Count the new number of remaining rows
    unsigned int newNumRows = 0;
    for(unsigned int i=0;i<numRows();i++)
    {
        if(!toBeDeleted[i])
        {
            newNumRows++;
        }
    }


    //Create a new array already sized in rows
    std::vector<std::vector<T> > newValues(newNumRows);

    //Move rows
    for(unsigned int i=0;i<numRows();i++)
    {
        if(!toBeDeleted[i])
        {
            newValues[i] = std::move(values[i]);
        }
    }

    //Set the new array and clear the old one efficiently
    values = std::move(newValues);

这是最有效的方法吗?

编辑:我只是认为我可以避免通过迭代向下移动行来避免分配新数组,这可能会稍微提高效率,并且代码也更加简单:

    unsigned int newIndex = 0;
    for(unsigned int oldIndex=0;oldIndex<values.size();oldIndex++)
    {
        if(!toBeDeleted[oldIndex])
        {
            if(oldIndex!=newIndex)
            {
                values[newIndex] = std::move(values[oldIndex]);
            }

            newIndex++;
        }
    }
    values.resize(newIndex);

谢谢!

这可以通过使用通常的“ 擦除-删除”惯用语的变体来解决,在std::remove_if内有一个lambda,它在要删除的迭代器范围内查找当前行的索引:

#include <algorithm>    // find, remove_if
#include <iostream>
#include <vector>

template<class T>
using M = std::vector<std::vector<T>>; // matrix

template<class T>
std::ostream& operator<<(std::ostream& os, M<T> const& m)
{
    for (auto const& row : m) {
        for (auto const& elem : row)
            os << elem << " ";
        os << "\n";
    }
    return os;
}

template<class T, class IdxIt>
void erase_rows(M<T>& m, IdxIt first, IdxIt last)
{
    m.erase(
        std::remove_if(
            begin(m), end(m), [&](auto& row) {
            auto const row_idx = &row - &m[0];
            return std::find(first, last, row_idx) != last;
        }), 
        end(m)
    );
}

int main()
{
    auto m = M<int> { { 0, 1, 2, 3 }, { 3, 4, 5, 6 }, { 6, 7, 8, 9 }, { 1, 0, 1, 0 } };
    std::cout << m << "\n";

    auto drop = { 1, 3 };
    erase_rows(m, begin(drop), end(drop));

    std::cout << m << "\n";
}

现场例子

注意 :因为从C ++ 11开始, std::vector具有移动语义,所以您的std::vector<std::vector<T>>行改组是使用简单的指针操作完成的,无论您的类型T (但是,如果您希望使用 -deletion,则会大不相同!)。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM