有点困境。
std::map<myClass, int> myMap;
void Distribute(){
float pool = 50;
int receivers = 0;
for(auto i = myMap.begin(); i != myMap.end(); i++){
if(i->second == 1) receivers++;
}
float distribution = pool/receivers;
for(auto i = myMap.begin(); i!= myMap.end; i++){
if(i->second == 0)continue;
i->first.value = distribution;
}
}
基本上,我想做的是找到地图的总大小,减去映射值为0的元素。此后,我想再次遍历同一张地图,但是使用我从上一个for循环中收集的数据。
这确实很丑陋且效率低下。当然,必须有某种方法可以将所有这些都以1为循环进行处理吗?也许理想情况下不需要第一个for循环?我不反对多余的工作,但是我不禁感到自己在这里写丑陋的代码,我真的很想输入一些信息。
答案 0 :(得分:2)
如果您自己插入了数据,则可以使用包含地图的包装器类
class Wrapper{
public:
int receivers = 0;
std::map<myClass, int> myMap;// be sure you have operator< for myClass
void insert(pair<myClass, int> item){
myMap.insert(item);
// count receivers when you insert , get receivers in constant time
if(item.second == 1){
receivers++;
}
}
};
void Distribute(){
float pool = 50;
Wrapper wrapper;
//insert your items by wrapper.insert(..) , not wrapper.myMap.insert(..)
float distribution = pool/wrapper.receivers;
for(auto& [i, j]: wrapper.myMap){
if(j == 1){
i.value = distribution;// be sure value is a public member of myClass
}
}
}
答案 1 :(得分:0)
假设所有内容都是单线程的。
您必须执行两次循环,但是您可以存储需要更改的元素的地址,因此不必进行两次测试。
请注意,此代码中有一个非常丑陋的const_cast。这是一个丑陋的原因。您不想更改地图的键;它会破坏地图的行为。我怀疑您可以通过采用第二个元素(0或1指示符)并将其设为myClass中的 field 来简化和改进您的设计。这样,您就不需要地图,只需一个myClass的集合,向量或列表即可。
我还必须为myClass定义哈希和operator ==。我省略了该部分以显示重要部分。
void Distribute(){
float pool = 50;
std::vector<myClass*> nonzeros;
for (auto iter = myMap.begin(); iter != myMap.end(); ++iter) {
if (iter->second == 1) { nonzeros.push_back(const_cast<myClass *>(&(iter->first))); }
}
if (nonzeros.empty()) return;
const float distribution = pool/nonzeros.size();
std::for_each(nonzeros.begin(), nonzeros.end(),
[distribution](decltype(nonzeros)::value_type pClass) {pClass->value = distribution;});
}