[英]How to get the smallest value group by variable value?
我是cob中的noob我想得到一些帮助,我想选择包含这些对象列表的向量中的最低值。 它有点选择聚合
class Label{
private:
std::string lbl;
int n;
public:
int getN() const { return this->n; }
std::string getlbl() const { return this->lbl; }
};
int main() {
std::vector<Label> my_vect = {
{"labl07", 0}, {"labl07", 0}, {"labl07", 0},
{"labl07", 0}, {"labl07", 0}, {"labl02", 232},
{"labl02", 232}, {"labl02", 233}, {"labl02", 234},
{"labl02", 230}, {"labl02", 233}, {"labl02", 234},
{"labl02", 229}, {"labl03", 379}, {"labl03", 377},
{"labl03", 379}, {"labl03", 381}, {"labl03", 380},
{"labl03", 377}, {"labl03", 381}, {"labl03", 372}
};
for(auto & v: my_vect)
{
cout <<"dis : "<< v.getlbl() <<" value " << v.getN() << endl;
}
return 0;
}
我希望能够做到这一点
dis : labl07 value 0
dis : labl02 value 229
dis : labl03 value 372
在下面的一些评论中他们使用地图关联容器我需要理解为什么而不是矢量。
在这种情况下尝试使用关联容器映射,因为使用vector更复杂。
string labelN;
string val;
int number;
map<string, int> values;
while (readingInput)
{
// input next line
fileInput >> labelN >> " ">> val>> "value " >> number;
if (number> values[val])
{
values[val] = number;
}
}
看完下面的一些建议。 我已经编写了这段代码,我认为除非有人写出更好的代码,否则它会起作用。 首先,您必须创建ganna添加到向量中的对象的构造函数。 其次,您必须添加一个函数,它将以聚合方式对矢量进行排序,然后将结果插入到地图中。 代码的最后一部分我将结果推送到你可能会使用它的向量中。
#include <iostream>
#include <sstream>
#include <string>
#include <map>
#include <vector>
#include <algorithm>
using namespace std;
class Label{
private:
std::string lbl;
int n;
public:
Label(std::string sp, int np): lbl(sp), n(np) {}
int getN() const { return this->n; }
std::string getlbl() const { return this->lbl; }
static bool sortByn( Label a, Label b )
{
if ( a.n < b.n ) return true;
if ( a.n == b.n && a.lbl < b.lbl ) return true;
return false;
}
};
int main() {
std::vector<Label> my_vect = {
{"labl07", 0}, {"labl07", 0}, {"labl07", 0},
{"labl07", 0}, {"labl07", 0}, {"labl02", 232},
{"labl02", 232}, {"labl02", 233}, {"labl02", 234},
{"labl02", 230}, {"labl02", 233}, {"labl02", 234},
{"labl02", 229}, {"labl03", 379}, {"labl03", 377},
{"labl03", 379}, {"labl03", 381}, {"labl03", 380},
{"labl03", 377}, {"labl03", 381}, {"labl03", 372}
};
for(auto & v: my_vect)
{
cout <<"dis : "<< v.getlbl() <<" value " << v.getN() << endl;
}
map<string,int> smallest;
string lbl;
int n;
for(auto & v: my_vect)
{
lbl = v.getlbl();
n = v.getN();
bool occurredBefore = smallest.count( lbl );
if ( occurredBefore )
{
if ( n < smallest[lbl] ) smallest[lbl] = n;
}
else
{
smallest[lbl] = n;
}
}
vector<Label> V;
for ( auto e : smallest ) V.push_back( { e.first, e.second } );
sort( V.begin(), V.end(), Label::sortByn );
for ( Label L : V ) cout << L.getlbl() << '\t' << L.getN() << '\n';
}
正如@Aconcagua建议的那样,您可以使用自定义比较器对矢量进行排序,以对矢量值进行排序:
[](Label const& x, Label const& y) {
return ((x.getlbl() < y.getlbl()) ||
((x.getlbl() == y.getlbl()) && (x.getN() < y.getN()))); };
您还需要一个构造函数来构造将插入到向量中的对象:
Label(std::string label, int value) : lbl(label), n(value){}
当迭代所有值时,只要标签是不同的,就打印元素。 因此,代码可能如下所示:
#include <iostream>
#include <vector>
#include <string>
#include <algorithm>
class Label{
private:
std::string lbl;
int n;
public:
Label(std::string label, int value) : lbl(label), n(value){}
int getN() const { return this->n; }
std::string getlbl() const { return this->lbl; }
};
int main() {
std::vector<Label> my_vect = {
{"labl07", 0}, {"labl07", 0}, {"labl07", 0},
{"labl07", 0}, {"labl07", 0}, {"labl02", 232},
{"labl02", 232}, {"labl02", 233}, {"labl02", 234},
{"labl02", 230}, {"labl02", 233}, {"labl02", 234},
{"labl02", 229}, {"labl03", 379}, {"labl03", 377},
{"labl03", 379}, {"labl03", 381}, {"labl03", 380},
{"labl03", 377}, {"labl03", 381}, {"labl03", 372}
};
std::sort(my_vect.begin(), my_vect.end(), [](Label const& x, Label const& y) {
return ((x.getlbl() < y.getlbl()) || ((x.getlbl() == y.getlbl()) && (x.getN() < y.getN()))); });
std::string labelToPrint;
for(const auto& v: my_vect)
{
if (labelToPrint.compare(v.getlbl()) != 0)
{
std::cout <<"dis : "<< v.getlbl() <<" value " << v.getN() << std::endl;
labelToPrint = v.getlbl();
}
}
return 0;
}
您可以使用multimap来执行此操作,请考虑以下示例(和注释)
#include<iostream>
#include<string>
#include<map>
#include<vector>
#include<algorithm>
struct x{
std::string s_value;
int i_value;
};
int main() {
std::vector<x> v{
{"01", 11},
{"02", 9},
{"03", 27},
{"01", 3},
{"02", 7},
{"03", 34},
{"01", 2},
{"02", 6},
{"03", 11},
};
// get unique keys
std::vector<std::string> keys {};
for(auto& x_value: v){
// if key is not present in keys yet put it there
if(std::find(keys.begin(),keys.end(), x_value.s_value) == keys.end()){
keys.push_back(x_value.s_value);
}
}
std::multimap<std::string, int> mmap;
for(auto& x_value : v){
//put values from vector into multimap
mmap.insert( decltype(mmap)::value_type(x_value.s_value, x_value.i_value) );
}
for(auto& key : keys){
// for each value we expect to be in multimap get range of values
std::vector<int> values{};
auto range = mmap.equal_range(key);
// put vaules for range into vector
for(auto i = range.first; i!= range.second; ++i){
values.push_back(i->second);
}
// sort vector
std::sort(values.begin(), values.end());
// print the least value in range corresponding to key, if there was any
if(!values.empty()){
std::cout<<key<<" "<<values[0]<<std::endl;
}
}
return 0;
}
虽然asdoud的答案在技术上是正确的(参考编辑,修订版3),但它使用多个地图查找,可以通过以下变体避免:
for(auto & v: my_vect)
{
int n = v.getN();
// pre-C++11 variant:
//auto entry = smallest.insert(std::make_pair(v.getlbl(), n));
// since C++11:
auto entry = smallest.emplace(v.getlbl(), n);
if(!entry.second)
{
if(n < entry.first->second)
entry.first->second = n;
}
}
进一步改进:字符串仍然被复制,实际上并不是必需的,因为地图的寿命不会长于包含字符串的向量。 因此,如果lbl
作为const引用返回,我们可以使用std::reference_wrapper<std::string>
作为映射键(甚至使用适当的自定义比较器的char const*
)。
您可以使用range-v3库轻松完成此操作:
auto groups = my_vect | ranges::view::group_by(
[](const Label& l1, const Label& l2){ return l1.getlbl() == l2.getlbl(); });
for (const auto & group : groups) {
auto min = ranges::min(group,
[](const Label& l1, const Label& l2){ return l1.getN() < l2.getN(); });
std::cout << min.getlbl() << ": " << min.getN() << std::endl;
}
输出:
labl07: 0
labl02: 229
labl03: 372
请注意,对于更高性能的getlbl()
通过const引用返回。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.