簡體   English   中英

如何通過變量值獲取最小值組?

[英]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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM