删除两个向量C ++中的相似元素(Deleting like elements in two vectors C++)
我试图搜索两个相同的元素的矢量(每个任何大小),然后删除这两个元素。
我的实现如下:
for (int i = vec1.size() - 1; i >= 0; i--) { for (int j = 0; j < vec2.size(); j++) { if (vec1[i] == vec2[j]) { vec1.erase(vec1.begin() + i); vec2.erase(vec2.begin() + j); } } }
然而,虽然这适用于大多数情况,但我遇到了一些它没有。 这是我通过这些向量迭代的方式,还是我只是这样做错了?
I am trying to search two vectors (each of any size) for elements that are identical and then delete both elements.
My implementation is as follows:
for (int i = vec1.size() - 1; i >= 0; i--) { for (int j = 0; j < vec2.size(); j++) { if (vec1[i] == vec2[j]) { vec1.erase(vec1.begin() + i); vec2.erase(vec2.begin() + j); } } }
However, while this works for most cases, I am running into some where it doesn't. Is it the way I am iterating through these vectors or am I just going about this all wrong?
原文:https://stackoverflow.com/questions/50051153
最满意答案
实际上你根本不需要向后迭代。 在这种情况下,您的代码可以是:
for (int i = 0; i < vec1.size(); i++) { for (int j = 0; j < vec2.size(); j++) { if (vec1[i] == vec2[j]) { vec1.erase(vec1.begin() + i); vec2.erase(vec2.begin() + j); } } }
但等等......我们擦除一个元素后会发生什么? 然后它之后的所有元素的索引都减少了1,所以我们将跳过下一个项目! 要解决这个问题,我们可以添加这个小修改:
vec1.erase(vec1.begin() + i--); vec2.erase(vec2.begin() + j--); ^^^^
即使我们通过擦除来改变大小,这也会起作用,因为我们正在检查每个循环的
vec2
的大小! 但是如果我们最终删除vec1
的最后一项呢? 我们不会再次比较它的大小,直到我们一直遍历vec2
,这将是你的vec1 = {2}, vec2 = {2, 2, 2}
示例中的一个问题。 为了解决这个问题,我们可以突破内循环并重复检查vec2
。把它们放在一起(并将你的下标操作符改为
.at()
调用,这样我们就可以检查边界了)你会得到:for (int i = 0; i < vec1.size(); i++) { for (int j = 0; j < vec2.size(); j++) { if (vec1.at(i) == vec2.at(j)) { vec1.erase(vec1.begin() + i--); vec2.erase(vec2.begin() + j--); break; } } }
(在这里看到它: ideone )
You don't actually need to iterate backwards at all. In which case your code can be:
for (int i = 0; i < vec1.size(); i++) { for (int j = 0; j < vec2.size(); j++) { if (vec1[i] == vec2[j]) { vec1.erase(vec1.begin() + i); vec2.erase(vec2.begin() + j); } } }
But wait up...what happens after we erase an element? Then all of the elements after it have their indexes decreased by 1, so we'll skip the next item! To fix that we can add this small modification:
vec1.erase(vec1.begin() + i--); vec2.erase(vec2.begin() + j--); ^^^^
This will work even when we change the size by erasing, because we're checking the size of the
vec2
every loop! But what if we end up erasing the last item ofvec1
? We don't compare its size again until we've iterated all the way throughvec2
, which will be a problem in yourvec1 = {2}, vec2 = {2, 2, 2}
example. To fix that we can just break out of the inner loop and repeat the check onvec2
.Put it all together (and change your subscript operator into
.at()
calls so we'll have bounds checking) and you get:for (int i = 0; i < vec1.size(); i++) { for (int j = 0; j < vec2.size(); j++) { if (vec1.at(i) == vec2.at(j)) { vec1.erase(vec1.begin() + i--); vec2.erase(vec2.begin() + j--); break; } } }
(See it in action here: ideone)
相关问答
更多-
看起来,所有常规STL算法都不符合你想要做的事情: std::swap_ranges几乎就在那里,但它要求你交换等长的范围std::rotate也不会坏,但它要求一个范围的终点等于第二个范围的开始点。 // pseudo-splice on vector v1.insert(v1.begin() + 2 + 2, v2.begin() + 3, v2.begin() + 3 + 3); v2.erase(v2.begin() + 3, v2.begin() + 3 + 3); // pseudo-spli ...
-
下面是如何使用STL set_intersection和set_difference来获得你想要的内容的例子: class Item { public: Item(int i):ItemId(i){} int ItemId; string ItemDescription; float ItemPrice; bool operator<(const Item& rhs) { return ItemId < rhs.ItemId; } bool ...
-
您正在寻找的算法通常被命名为“合并”。 基本上,您对两个数据集进行排序,然后成对查看数据:如果键相等,则处理并输出该对,否则只处理和前进最小的一个。 您还必须处理两个列表中的一个在另一个列表之前结束的情况(可以通过使用保证高于您需要处理的任何值的特殊标志值来避免这种情况)。 以下是用于合并的伪代码 排序vector1 排序vector2 设置index1 = index2 = 0; 循环,直到index1 >= vector1.size()和index2 >= vector2.size() (换句话说,直到 ...
-
std::swap期望引用,而不是迭代器: std::swap(v1[m], v2[n]); std::swap expects references, not iterators: std::swap(v1[m], v2[n]);
-
C ++向量问题(C++ Vectors Problem)[2022-02-11]
由于sample向量是指针列表,因此您需要确保为添加到向量的每个元素创建一个新的CvMat实例。 否则,听起来你的所有元素都指向同一个东西( g )。 如果CvMat有一个拷贝构造函数,你可以通过这样做来解决它: vectorsample; for(int x =0 ; x<29; x+=2) { // ... sample.push_back(*g); } 这将创建一个CvMat 对象的向量, push_back(*g)生成矩阵的副本并将其推送到向量的背面。 Since ... -
如果元素可以以某种有意义的方式进行散列 ,则可以通过使用散列映射获得预期的O(n)性能:将列表A中的所有元素插入到散列映射中,并且对于列表B中的每个元素,检查它是否存在于散列映射中。 在C ++中,我相信unordered_map是标准的hashmap实现(虽然我自己没有使用它)。 If the elements can be hashed in some meaningful way, you can get expected O(n) performance by using a hashmap: In ...
-
std::remove_if()不能与set一起使用。 从集合中删除值的唯一方法是使用erase()方法。 std::remove_if()通过逐字复制它们从序列中删除值,并返回新序列的结束迭代器值。 你使用结束迭代器值调用erase() ,但这还不够。 std::remove_if()意味着与序列容器一起使用,例如std::vector或std::list ,您可以通过复制它们来删除单个元素。 但这不适用于std::set() ,因为std::remove_if()对set的erase()方法一无所知,这 ...
-
实际上你根本不需要向后迭代。 在这种情况下,您的代码可以是: for (int i = 0; i < vec1.size(); i++) { for (int j = 0; j < vec2.size(); j++) { if (vec1[i] == vec2[j]) { vec1.erase(vec1.begin() + i); vec2.erase(vec2.begin() + j); } } ...
-
vector
C(A); C.insert(C.end(), B.begin(), B.end()); vector C(A); C.insert(C.end(), B.begin(), B.end()); -
尝试使用which和== which(a==b) #[1] 1 2 4 5 6 7 8 10 使用@David Arenburg的例子 set.seed(12) a <- sample(c(0,1),10,replace=TRUE) b <- sample(c(0,1),10,replace=TRUE) c <- sample(c(0,1),10,replace=TRUE) # added which(rowSums(cbind(a,b,c)==a)==3) #[1] 1 2 5 ...