当在另一个单个向量中实现条件时,擦除 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
调用会擦除整个范围,而不仅仅是单个值,因此有可能比给出的第一个就地解决方案更快(但你必须对它们计时,我不能保证哪个更快)。
我有一个矩阵(向量的向量),换句话说,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
调用会擦除整个范围,而不仅仅是单个值,因此有可能比给出的第一个就地解决方案更快(但你必须对它们计时,我不能保证哪个更快)。