如何更新 std::set 的现有元素?
我有一个 std::set
,我想更新一些值 其中的现有元素。请注意,我正在更新的值不会更改集合中的顺序:
#include <iostream>
#include <set>
#include <utility>
struct Foo {
Foo(int i, int j) : id(i), val(j) {}
int id;
int val;
bool operator<(const Foo& other) const {
return id < other.id;
}
};
typedef std::set<Foo> Set;
void update(Set& s, Foo f) {
std::pair<Set::iterator, bool> p = s.insert(f);
bool alreadyThere = p.second;
if (alreadyThere)
p.first->val += f.val; // error: assignment of data-member
// ‘Foo::val’ in read-only structure
}
int main(int argc, char** argv){
Set s;
update(s, Foo(1, 10));
update(s, Foo(1, 5));
// Now there should be one Foo object with val==15 in the set.
return 0;
}
是否有任何简洁的方法可以做到这一点?或者我是否必须检查该元素是否已经存在,如果是,则将其删除,添加值并重新插入?
I have a std::set<Foo>
, and I'd like to update some value of
an existing element therein. Note that the value I'm updating does not change the order in the set:
#include <iostream>
#include <set>
#include <utility>
struct Foo {
Foo(int i, int j) : id(i), val(j) {}
int id;
int val;
bool operator<(const Foo& other) const {
return id < other.id;
}
};
typedef std::set<Foo> Set;
void update(Set& s, Foo f) {
std::pair<Set::iterator, bool> p = s.insert(f);
bool alreadyThere = p.second;
if (alreadyThere)
p.first->val += f.val; // error: assignment of data-member
// ‘Foo::val’ in read-only structure
}
int main(int argc, char** argv){
Set s;
update(s, Foo(1, 10));
update(s, Foo(1, 5));
// Now there should be one Foo object with val==15 in the set.
return 0;
}
Is there any concise way to do this? Or do I have to check if the element is already there, and if so, remove it, add the value and re-insert?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(6)
由于
val
不参与比较,因此可以将其声明为mutable
这意味着
val
的值可能会在逻辑常量 Foo 中发生变化,这意味着它不应该影响其他比较运算符等。或者您可以只删除和插入,如果插入使用
之前的位置,则需要 O(1) 额外时间(与访问和修改相比)就在旧的作为提示之后。像这样的东西:
Since
val
is not involved in comparison, it could be declaredmutable
This implies that the value of
val
may change in a logically-const Foo, which means that it shouldn't affect other comparison operators etc.Or you could just remove and insert, that takes O(1) additional time (compared to accessing and modifying) if insertion uses the position
just beforejust after the old one as the hint.Something like:
不要尝试通过解决
set
中项目的常量性来解决此问题。相反,为什么不使用map
,它已经表达了您正在建模的键值关系,并提供了更新现有元素的简单方法。Don't try to solve this problem by working around the const-ness of items in a
set
. Instead, why not usemap
, which already expresses the key-value relationship you are modeling and provides easy ways to update existing elements.使
val
可变为:现在,即使
foo
是 const,您也可以更改/修改/改变val
:顺便说一句,从您的代码中,您可以似乎认为如果 p.second 为 true,则该值已存在于集合中,因此您更新关联的值。我想,你搞错了。事实上恰恰相反。 cpluscplus 的 doc 说,
我认为这是正确的。
但是,如果您使用 std::map,您的解决方案将很简单:
这段代码的作用是什么?如果映射中不存在该键,
m[value.first]
将创建一个新条目,并且新条目的值是int
的默认值,即零。因此它将value.second
添加到zero
。否则,如果该键存在,那么它只是将value.second
添加到它。也就是说,上面的代码相当于这样:但这太多了,不是吗?它的性能并不好。早期的更加简洁并且性能非常好。
Make
val
mutable as:Now you can change/modify/mutate
val
even iffoo
is const:By the way, from your code, you seem to think that if
p.second
is true, then the value already existed in the set, and therefore you update the associated value. I think, you got it wrong. It is in fact other way round. The doc at cpluscplus says,which is correct, in my opinion.
However, if you use
std::map
, your solution would be straightforward:What does this code do?
m[value.first]
creates a new entry if the key doesn't exist in the map, and value of the new entry is default value ofint
which is zero. So it addsvalue.second
tozero
. Or else if the key exists, then it simply addsvalue.second
to it. That is, the above code is equivalent to this:But this is too much, isn't it? It's performance is not good. The earlier one is more concise and very performant.
如果您知道自己在做什么(集合元素本身不是 const 并且您没有更改参与比较的成员),那么您可以放弃 const 性:
If you know what you're doing (the set elements are not const per se and you're not changing members involved in comparison), then you can just cast away const-ness:
不使用单独的提示,而是使用擦除的返回值作为下一个迭代器位置
Instead of separate hint, use the erase's return value for the next iterator position
如果您有 KEY ,您可以使用 MAP 女巫可以非常快速地访问您的元素。在这种情况下,我认为使用 MAP 是实现最快速度的更好方法。标准::地图
you can use MAP witch has very fast access to your element if you have KEY . in this case i think using MAP would be better way to achieve fastest speed . STD::MAP