当在另一个单个向量中实现条件时,擦除 2D 向量的行和列?

erase rows and colums of a 2D vector, when a condition is achieved in another single vector?

我有一个矩阵(向量的向量),换句话说,2D 向量 (6 X 6) 个元素 <double>,然后我有一个包含 6 个元素的向量 <int>。带整数的向量只有“0”和“1”。然后,当在整数向量 (1D) 中找到“0”时,我正在寻找一种方法来删除二维向量的行和列。这次只有 6 X 6,但以后会是 100 X 100 左右。

我所做的是使用迭代器,我成功地删除了行,但现在我不知道如何处理列。

这是我的代码。

#include <iostream>
#include <vector>
#include <iomanip>

int main() {

    std::vector <int> boundaryConditions = { 0,1,1,1,0,0 };
    std::vector <std::vector<double>> matrix = { {1.46371e+07, 1.46371e+07, -1.46371e+07, -1.46371e+07, 0, 0},
    {1.46371e+07, 5.60371e+07, -1.46371e+07, -1.46371e+07, 0, -4.14e+07},
    {-1.46371e+07, -1.46371e+07, 5.60371e+07, 1.46371e+07, -4.14e+07, 0},
    {-1.46371e+07, -1.46371e+07, 1.46371e+07, 1.46371e+07, 0, 0},
    {0, 0, -4.14e+07, 0, 4.14e+07, 0},
    {0, -4.14e+07, 0, 0, 0, 4.14e+07}};

    int i = 0;
    std::vector<int>::iterator it = boundaryConditions.begin();
    while (it != boundaryConditions.end())
    {
        if (*it == 0)
        {
            it = boundaryConditions.erase(it);
            matrix.erase(matrix.begin() + i);
        }
        else
        {
            it++;
            i++;
        }
    }

    for (int i = 0; i < matrix.size(); i++)
    {
        for (int j = 0; j < matrix[i].size(); j++)
        {
            std::cout << matrix[i][j] << std::setw(15);
        }
        std::cout << "\n";
    }
    system("pause>0");
}

也许这会有所帮助,但尚未经过全面测试: 令 A 为 binaryConditions 数组,

void reduce(std::vector<int> A, std::vector<int> &target) {
    int i = 0, j = 0;
    int nOnes = 0;
    while (i<A.size() && j < A.size()) {
        if (A[i] != 0) {
            ++i;
            nOnes++;
        }
        else {
            j = max(i + 1, j);
            while (j < A.size() && A[j] == 0) ++j;
            if (j >= A.size()) break;
            swap(A[i], A[j]);
            swap(target[i], target[j]);
        }
    }
    A.resize(nOnes);
    target.resize(nOnes);
}

您可以在删除行后创建一个新矩阵。

std::vector<std::vector<double>> removeColumns(const std::vector<int>& boundaryConditions, 
                                               const std::vector<std::vector<double>>& matrix)
{
    std::vector<std::vector<double>> returnValue(matrix.size());
    size_t curRow = 0;
    size_t curCol = 0;
    for (auto& v : returnValue)
    {
        for (size_t curCol = 0; curCol < matrix[0].size(); ++curCol)
        {
              if (boundaryConditions[curCol] == 1)
                  v.push_back(matrix[curRow][curCol]);
        }
        ++curRow;
    }
    return returnValue;
}

然后你会这样称呼它,因为你已经从 matrix:

中删除了行
matrix = removeColumns({0,1,1,1,0,0}, matrix); 

这里是Live Example.


如果你想要一个就地解决方案,这里有一个例子:

void removeColumns(const std::vector<int>& boundaryConditions, std::vector<std::vector<double>>& matrix)
{
    size_t curCol = 0;
    for (size_t i = 0; i < boundaryConditions.size(); ++i)
    {
        if (boundaryConditions[i] == 0)
        {
            for (auto& v : matrix)
               v.erase(v.begin() + curCol);
        }
        else
          ++curCol;
    }            
}

那么就这样调用:

removeColumns({0,1,1,1,0,0}, matrix);

这是一个Live Example


另一个解决方案,如果对您可行的话,是用一个值标记要删除的每个条目,可能是 std::numeric_limits<double>::max()。然后在第二遍中,使用 erase/remove 习语,从而减少所需的 erase 调用次数。

这是一个例子:

void removeColumns(const std::vector<int>& boundaryConditions,
                   std::vector<std::vector<double>>& matrix)
{
    // Mark the entries to delete
    for (size_t i = 0; i < boundaryConditions.size(); ++i)
    {
        if (boundaryConditions[i] == 0)
            std::for_each(matrix.begin(), matrix.end(),[&](std::vector<double>& vect) 
             { vect[i] = std::numeric_limits<double>::max(); });
    }            

    // One pass through the matrix to remove the marked entries.
    for (auto& v : matrix)
        v.erase(std::remove(v.begin(), v.end(), std::numeric_limits<double>::max()), v.end());
}

这是一个Live Example

请注意 std::remove 并没有真正删除任何东西,因此不会招致实际 erase 的惩罚。

单个 erase 调用会擦除整个范围,而不仅仅是单个值,因此有可能比给出的第一个就地解决方案更快(但你必须对它们计时,我不能保证哪个更快)。