根据 C++ 中同一列中 2 行的比较,删除 2D std::vector 中的列
Delete column in 2D std::vector depending on comparison of 2 rows in same column in C++
我有一个二维 std::vector < std::vector <double> >
数组,由三行和未知数量的列组成。我想删除值 row 0 > row 1
的任何列。这是我的努力:
#include <iostream>
#include <vector>
using namespace std;
template <typename T>
inline void printArray (const std::vector< std::vector< T > >& key_array) {
for (int i = 0; i < key_array.size(); i++) {
for (int j = 0; j < key_array[i].size(); j++) {
std::cout << key_array[i][j] << "\t";
}
std::cout << "\n";
}
std::cout << "\n";
}
int main()
{
std::vector< std::vector <int> > fog {{1,1,2,1},{2,2,1,2},{3,3,3,3}};
printArray(fog);
for (int i = 0; i < fog[0].size(); ++i) {
for (int j = 0; j < fog.size(); ++j) {
if (fog[0][i] > fog[1][i]) {
fog[j].erase(fog[j].begin() + i);
}
}
}
printArray(fog);
数组初始为:
1 1 2 1
2 2 1 2
3 3 3 3
我希望它变成:
1 1 1
2 2 2
3 3 3
相反,我得到:
1 1 1
2 2 1 2
3 3 3 3
我想这个问题是因为数组的大小随着元素的删除而改变,使循环条件无效,and/or 迭代器被删除。但是通过这种观察,我已经达到了我的(相当有限的)极限。
如有任何建议,我将不胜感激。
您的代码“正确”,但不能就地运行。一种解决方案是复制数组并将其替换为副本,同时迭代旧数组:
#include <iostream>
#include <vector>
using namespace std;
template <typename T>
inline void printArray (const std::vector< std::vector< T > >& key_array)
{
for (int i = 0; i < key_array.size(); i++) {
for (int j = 0; j < key_array[i].size(); j++) {
std::cout << key_array[i][j] << "\t";
}
std::cout << "\n";
}
std::cout << "\n";
}
int main()
{
std::vector< std::vector <int> > fog {{1,1,2,1},{2,2,1,2},{3,3,3,3}};
printArray(fog);
auto fog2 = fog;
for (int i = 0; i < fog[0].size(); ++i)
{
for (int j = 0; j < fog.size(); ++j)
{
if (fog[0][i] > fog[1][i])
{
fog2[j].erase(fog2[j].begin() + i);
}
}
}
printArray(fog2);
}
如果想就地执行,您需要更改 for 循环逻辑。
此解决方案受@RoQuOTriX 启发,迭代原始二维 std::vector
数组并有选择地将所需列复制到新数组(而不是擦除新数组中不需要的列)。该策略解决了迭代不断变化的数组的问题。
#include <iostream>
#include <vector>
template <typename T>
inline void printArray (const std::vector< std::vector< T > >& key_array)
{
for (int i = 0; i < key_array.size(); i++) {
for (int j = 0; j < key_array[i].size(); j++) {
std::cout << key_array[i][j] << "\t";
}
std::cout << "\n";
}
std::cout << "\n";
}
int main()
{
std::vector< std::vector <int> > fog {{1,2,1,2,2,1},{2,1,2,1,1,2},{3,3,3,3,3,3}};
printArray(fog);
std::vector< std::vector < double > > fog2(fog.size());
for (int i = 0; i < fog[0].size(); ++i) {
for (int j = 0; j < fog.size(); ++j) {
if (fog[0][i] < fog[1][i]) {
fog2.at(j).push_back(fog[j][i]);
}
}
}
printArray(fog2);
}
雾是:
1 2 1 2 2 1
2 1 2 1 1 2
3 3 3 3 3 3
并且,根据需要,fog2 是:
1 1 1
2 2 2
3 3 3
此方法会删除 row 0 > row 1
中的所有列,无论是分开的还是连续的,而不会导致分段错误。
但是这种方式比较“重”,需要深拷贝。如果有人有更有效的解决方案,我很想听听!
以下方法“就地”删除所需的列,而不是复制。该策略改编自How to delete column in 2d vector, c++
#include <iostream>
#include <vector>
using namespace std;
template <typename T>
inline void printArray (const std::vector< std::vector< T > >& key_array) {
for (int i = 0; i < key_array.size(); i++) {
for (int j = 0; j < key_array[i].size(); j++) {
std::cout << key_array[i][j] << "\t";
}
std::cout << "\n";
}
std::cout << "\n";
}
int main()
{
std::vector< std::vector <int> > fog {{2,1,1,2,1,2,1,2,1,2},{1,2,2,1,2,1,2,1,2,1},{3,3,3,3,3,3,3,3,3,3}};
printArray(fog);
for (int i = 0; i < fog[0].size(); ++i)
{
if (fog[0][i] > fog[1][i]) {
/* // Alternative
std::for_each(fog.begin(), fog.end(), [&](std::vector<int>& row) {
row.erase(std::next(row.begin(), i));
});
*/
for(auto& row:fog) row.erase(std::next(row.begin(), i));
// accounts for deleted column
--i;
}
}
printArray(fog);
}
循环前的雾是:
2 1 1 2 1 2 1 2 1 2
1 2 2 1 2 1 2 1 2 1
3 3 3 3 3 3 3 3 3 3
循环后的雾是:
1 1 1 1 1
2 2 2 2 2
3 3 3 3 3
也许令人惊讶的是,与上面我(@Bob)使用的复制方法相比,就地删除并没有加快操作速度。也许两种方法中内存占用的数量最终是相似的。但是,由于没有使用原地删除策略进行复制,因此它在内存占用方面可能更有效。
我有一个二维 std::vector < std::vector <double> >
数组,由三行和未知数量的列组成。我想删除值 row 0 > row 1
的任何列。这是我的努力:
#include <iostream>
#include <vector>
using namespace std;
template <typename T>
inline void printArray (const std::vector< std::vector< T > >& key_array) {
for (int i = 0; i < key_array.size(); i++) {
for (int j = 0; j < key_array[i].size(); j++) {
std::cout << key_array[i][j] << "\t";
}
std::cout << "\n";
}
std::cout << "\n";
}
int main()
{
std::vector< std::vector <int> > fog {{1,1,2,1},{2,2,1,2},{3,3,3,3}};
printArray(fog);
for (int i = 0; i < fog[0].size(); ++i) {
for (int j = 0; j < fog.size(); ++j) {
if (fog[0][i] > fog[1][i]) {
fog[j].erase(fog[j].begin() + i);
}
}
}
printArray(fog);
数组初始为:
1 1 2 1
2 2 1 2
3 3 3 3
我希望它变成:
1 1 1
2 2 2
3 3 3
相反,我得到:
1 1 1
2 2 1 2
3 3 3 3
我想这个问题是因为数组的大小随着元素的删除而改变,使循环条件无效,and/or 迭代器被删除。但是通过这种观察,我已经达到了我的(相当有限的)极限。
如有任何建议,我将不胜感激。
您的代码“正确”,但不能就地运行。一种解决方案是复制数组并将其替换为副本,同时迭代旧数组:
#include <iostream>
#include <vector>
using namespace std;
template <typename T>
inline void printArray (const std::vector< std::vector< T > >& key_array)
{
for (int i = 0; i < key_array.size(); i++) {
for (int j = 0; j < key_array[i].size(); j++) {
std::cout << key_array[i][j] << "\t";
}
std::cout << "\n";
}
std::cout << "\n";
}
int main()
{
std::vector< std::vector <int> > fog {{1,1,2,1},{2,2,1,2},{3,3,3,3}};
printArray(fog);
auto fog2 = fog;
for (int i = 0; i < fog[0].size(); ++i)
{
for (int j = 0; j < fog.size(); ++j)
{
if (fog[0][i] > fog[1][i])
{
fog2[j].erase(fog2[j].begin() + i);
}
}
}
printArray(fog2);
}
如果想就地执行,您需要更改 for 循环逻辑。
此解决方案受@RoQuOTriX 启发,迭代原始二维 std::vector
数组并有选择地将所需列复制到新数组(而不是擦除新数组中不需要的列)。该策略解决了迭代不断变化的数组的问题。
#include <iostream>
#include <vector>
template <typename T>
inline void printArray (const std::vector< std::vector< T > >& key_array)
{
for (int i = 0; i < key_array.size(); i++) {
for (int j = 0; j < key_array[i].size(); j++) {
std::cout << key_array[i][j] << "\t";
}
std::cout << "\n";
}
std::cout << "\n";
}
int main()
{
std::vector< std::vector <int> > fog {{1,2,1,2,2,1},{2,1,2,1,1,2},{3,3,3,3,3,3}};
printArray(fog);
std::vector< std::vector < double > > fog2(fog.size());
for (int i = 0; i < fog[0].size(); ++i) {
for (int j = 0; j < fog.size(); ++j) {
if (fog[0][i] < fog[1][i]) {
fog2.at(j).push_back(fog[j][i]);
}
}
}
printArray(fog2);
}
雾是:
1 2 1 2 2 1
2 1 2 1 1 2
3 3 3 3 3 3
并且,根据需要,fog2 是:
1 1 1
2 2 2
3 3 3
此方法会删除 row 0 > row 1
中的所有列,无论是分开的还是连续的,而不会导致分段错误。
但是这种方式比较“重”,需要深拷贝。如果有人有更有效的解决方案,我很想听听!
以下方法“就地”删除所需的列,而不是复制。该策略改编自How to delete column in 2d vector, c++
#include <iostream>
#include <vector>
using namespace std;
template <typename T>
inline void printArray (const std::vector< std::vector< T > >& key_array) {
for (int i = 0; i < key_array.size(); i++) {
for (int j = 0; j < key_array[i].size(); j++) {
std::cout << key_array[i][j] << "\t";
}
std::cout << "\n";
}
std::cout << "\n";
}
int main()
{
std::vector< std::vector <int> > fog {{2,1,1,2,1,2,1,2,1,2},{1,2,2,1,2,1,2,1,2,1},{3,3,3,3,3,3,3,3,3,3}};
printArray(fog);
for (int i = 0; i < fog[0].size(); ++i)
{
if (fog[0][i] > fog[1][i]) {
/* // Alternative
std::for_each(fog.begin(), fog.end(), [&](std::vector<int>& row) {
row.erase(std::next(row.begin(), i));
});
*/
for(auto& row:fog) row.erase(std::next(row.begin(), i));
// accounts for deleted column
--i;
}
}
printArray(fog);
}
循环前的雾是:
2 1 1 2 1 2 1 2 1 2
1 2 2 1 2 1 2 1 2 1
3 3 3 3 3 3 3 3 3 3
循环后的雾是:
1 1 1 1 1
2 2 2 2 2
3 3 3 3 3
也许令人惊讶的是,与上面我(@Bob)使用的复制方法相比,就地删除并没有加快操作速度。也许两种方法中内存占用的数量最终是相似的。但是,由于没有使用原地删除策略进行复制,因此它在内存占用方面可能更有效。