创建std :: set只复制一个元素,如何解决这个问题?

时间:2018-05-27 18:26:23

标签: c++ set

v_map存储了正确的信息量,但是当我尝试使用 std :: set 时,它只复制一个元素,我假设第一个< / em>一个。这是我第一次使用 std :: set ,也许我在这里想念一下......谢谢你的帮助!

typedef std::map<std::string,std::pair<int,int>> points_map;
void list_average(points_map &v_map)
{
    Comparator compFunctor = [](std::pair<std::string,std::pair<int,int>> elem1,std::pair<std::string,std::pair<int,int>> elem2)
            {
                std::pair<int,int> it = elem1.second;
                std::pair<int,int> jt = elem2.second;
                return it.first < jt.first;
            };
    std::set<std::pair<std::string,std::pair<int,int>>,Comparator> v_set(v_map.begin(),v_map.end(),compFunctor);
    for (std::pair<std::string,std::pair<int,int>> it : v_set)
    {
        std::pair<int,int> jt = it.second;
        std::cout << it.first << " " << (jt.second - jt.first) / jt.first<< std::endl;

    }
}

注意以下是完整程序,我为丑陋的代码提前道歉,以及代码的长度,我重写了我的代码上部的名称,在完整代码中,此特定功能称为 list_atlag

#include <iostream>
#include <string>
#include <map>
#include <set>
#include <vector>
#include <codecvt>
#include <iterator>
#include <numeric>
#include <functional>

#include <boost/filesystem.hpp>
#include <boost/foreach.hpp>
#include <boost/program_options.hpp>
#include <boost/tokenizer.hpp>

class Adatok
{
  public:
    Adatok(std::string name, std::string path, std::string date, int points) : _name(name), _path(path), _date(date), _points(points) {}
    Adatok(const Adatok &other) = default;
    Adatok &operator=(const Adatok &other) = default;

    std::string get_name() { return _name; }
    std::string get_path() { return _path; }
    std::string get_date() { return _date; }
    int get_points() { return _points; }

  private:
    std::string _name;
    std::string _path;
    std::string _date;
    int _points;
};
class Ranglista
{
  public:
    Ranglista(std::string name, int points) : _name(name), _points(points) {}
    Ranglista(const Ranglista &other) = default;
    Ranglista &operator=(const Ranglista &other) = default;

    std::string get_name() { return _name; }
    int get_points() { return _points; }
    bool operator<(const Ranglista &other)
    {
        return _points > other._points;
    }

  private:
    std::string _name;
    int _points;
};
class Vedes
{
  public:
    Vedes(std::string name, int point) : _name(name), _point(point) { _count++; }
    Vedes(const Vedes &other) = default;
    Vedes &operator=(const Vedes &other) = default;
    std::string get_name() { return _name; }
    int get_point() { return _point; }
    int get_count() { return _count; }
    void set_stuff(int &points)
    {
        _point += points;
        _count++;
    }
    bool operator<(const Vedes &other)
    {
        return _count > other._count;
    }

  private:
    std::string _name;
    int _point;
    int _count = 0;
};

typedef std::map<std::string, int> path_value; //minden path + az erteke
typedef std::vector<Adatok> name_path_date;    //bejegyzesek
typedef std::vector<Ranglista> ranglista;      //ranglista
typedef std::map<std::string,std::pair<int,int>> vedes_vec;          //vedesek
typedef std::function<bool(std::pair<std::string,std::pair<int,int>>,std::pair<std::string,std::pair<int,int>>)> Comparator;


void create_pv(path_value &, boost::filesystem::path);                                   //feltolti a path+ertek map-ot
void create_npd(name_path_date &, path_value &, std::string input);                      //feltolti a bejegyzesek vektorat + mindenki pontszama map
void create_np(name_path_date &, path_value &);                                          // name + path map
void list_np(path_value &name_point);                                                    // nam + path kiiratas
void list_bejegyzesek(name_path_date &bejegyzesek);                                      // bejegyzesek vektora kiiratas
bool check_bejegyzesek(name_path_date &bejegyzesek, std::string name, std::string path); //van-e mar ilyen bejegyzes
void create_rl(ranglista &rl_vec, path_value &name_point);                               //ranglista feltoltes
void list_rl(ranglista &rl_vec);                                                         //ranglista kiiratas
void vedes_atlag(name_path_date &bejegyzesek, vedes_vec &v_vec);                         //vedes atlag map
void list_atlag(vedes_vec &v_vec);                                                       //vedes atlag kiiratas
bool check_vedes(vedes_vec &v_vec, std::string name);
void vedes_elem(vedes_vec &v_vec, std::string name, int &&points); //
//void accumulate_pv(path_value&);

int main(int argc, char **argv)
{
    std::vector<std::string> roots = {"City/Debrecen/Oktatás/Informatika/Programozás/DEIK/Prog1/", "City/Debrecen/Oktatás/Informatika/Programozás/DEIK/"};
    std::string input_file_name = "db-2018-05-06.csv";

    /* OPTIONS */
    boost::program_options::options_description desc("ALLOWED OPTIONS");
    desc.add_options()("help", "help msg")("root,r", boost::program_options::value<std::vector<std::string>>())("csv", boost::program_options::value<std::string>(), "comma separated values")("rank", "rang lista")("vedes", "labor vedesek");
    boost::program_options::positional_options_description pdesc;
    pdesc.add("root", -1);
    boost::program_options::variables_map vm;
    boost::program_options::store(boost::program_options::command_line_parser(argc, argv).options(desc).positional(pdesc).run(), vm);
    boost::program_options::notify(vm);

    int sum = 0;
    path_value pv_map;
    if (vm.count("help") || argc == 1)
    {
        std::cout << desc << std::endl;
        return 1;
    }
    if (vm.count("root"))
    {
        roots = vm["root"].as<std::vector<std::string>>();
        for (auto &i : roots)
        {
            boost::filesystem::path path(i);
            create_pv(pv_map, path);
        }
        for (path_value::iterator it{pv_map.begin()}; it != pv_map.end(); it++)
            sum += it->second;
        //std::cout << sum << std::endl;create_npd
        std::cout << std::accumulate(pv_map.begin(), pv_map.end(), 0, [](int value, const std::map<std::string, int>::value_type &p) { return value + p.second; });
        std::cout << std::endl;
    }

    if (vm.count("csv"))
    {
        //input_file_name = vm["csv"].as<std::string>();
        std::ifstream input_file{vm["csv"].as<std::string>()};
        name_path_date bejegyzesek;
        std::string temp;
        path_value name_point;

        while (getline(input_file, temp))
            create_npd(bejegyzesek, pv_map, temp);
        create_np(bejegyzesek, name_point);
        //list_bejegyzesek(bejegyzesek);
        //list_np(name_point);
        if (vm.count("rank"))
        {
            ranglista rl_vec;
            create_rl(rl_vec, name_point);
            list_rl(rl_vec);
        }
        if (vm.count("vedes"))
        {

            vedes_vec v_vec;
            vedes_atlag(bejegyzesek, v_vec);
            list_atlag(v_vec);
        }
        return 0;
    }
    return 0;
}

void create_pv(path_value &pv_map, boost::filesystem::path path)
{
    boost::filesystem::directory_iterator it{path}, eod;
    BOOST_FOREACH (boost::filesystem::path const &p, std::make_pair(it, eod))
    {
        if (boost::filesystem::is_regular_file(p))
        {
            boost::filesystem::ifstream regular_file{p};
            std::string temp;
            int sum = 0; //aktualis .props erteke
            while (getline(regular_file, temp))
            {
                temp.erase(0, temp.find_last_of('/'));
                temp.erase(0, temp.find_first_of(' '));
                sum += std::atoi((temp.substr(temp.find_first_of("0123456789"), temp.find_last_of("0123456789"))).c_str());
            }
            std::string result = p.string();
            std::string result_path = result.substr(0, result.find_last_of('/'));
            //std::cout << result_path << std::endl;
            //pv_map.insert(std::make_pair(result, sum));
            pv_map[result_path] = sum;
        }
        else
            create_pv(pv_map, p);
    }
}
//void accumulate_pv(path_value& pv_map)
//{
//   std::cout<<std::accumulate(pv_map.begin(),pv_map.end(),0,[](int value,const path_value::int& p){return value+p.second;});
//}
void create_npd(name_path_date &bejegyzesek, path_value &pv_map, std::string input)
{
    boost::tokenizer<boost::escaped_list_separator<char>> tokenizer{input};
    boost::tokenizer<boost::escaped_list_separator<char>>::iterator it{tokenizer.begin()};
    std::string name = *it;
    std::string path = *(++it);
    std::string date = *(++it);
    path = path.substr(2);
    if (!check_bejegyzesek(bejegyzesek, name, path))
        bejegyzesek.push_back(Adatok(name, path, date, pv_map["/home/erik/Documents/Programs/"+path]));
}
bool check_bejegyzesek(name_path_date &bejegyzesek, std::string name, std::string path)
{
    bool ok = false;
    for (name_path_date::iterator it{bejegyzesek.begin()}; it != bejegyzesek.end(); it++)
    {
        if ((it->get_name() == name) && (it->get_path() == path))
            ok = true;
    }
    return ok;
}
bool check_vedes(vedes_vec &v_vec, std::string name)
{
    vedes_vec::iterator it = v_vec.find(name);
    if (it != v_vec.end()) return true;
    else return false;
}
void vedes_elem(vedes_vec &v_vec, std::string name, int &&points)
{
    /*for (auto &it : v_vec)
        if (it.get_name() == name)
            it.set_stuff(points);
            */
    vedes_vec::iterator i  = v_vec.find(name);
    std::pair<int,int> it = i->second;
    //auto& jt = it->second;
    it.first++;
    it.second += points;
}
void create_np(name_path_date &bejegyzesek, path_value &name_point)
{
    for (name_path_date::iterator it{bejegyzesek.begin()}; it != bejegyzesek.end(); it++)
        if (name_point.count(it->get_name()) == 0)
            name_point.insert(std::make_pair(it->get_name(), it->get_points()));
        else
            name_point[it->get_name()] += it->get_points();
}
void list_np(path_value &name_point)
{
    for (path_value::iterator it{name_point.begin()}; it != name_point.end(); it++)
    {
        if (it->second)
            std::cout << it->first << " " << it->second << std::endl;
    }
}
void list_bejegyzesek(name_path_date &bejegyzesek)
{
    for (name_path_date::iterator it{bejegyzesek.begin()}; it != bejegyzesek.end(); it++)
        if (it->get_name() == "Varga Erik")
            std::cout << it->get_name() << " " << it->get_path() << " " << it->get_points() << std::endl;
}
void create_rl(ranglista &rl_vec, path_value &name_point)
{
    for (auto &it : name_point)
    {
        if (it.second > 0)
            rl_vec.push_back(Ranglista(it.first, it.second));
    }
    std::sort(rl_vec.begin(), rl_vec.end());
}
void list_rl(ranglista &rl_vec)
{
    for (auto &it : rl_vec)
        std::cout << it.get_name() << " " << it.get_points() << std::endl;
}
void vedes_atlag(name_path_date &bejegyzesek, vedes_vec &v_vec)
{
    std::string key = "City/Debrecen/Oktatás/Informatika/Programozás/DEIK/Prog1/Labor/Védés/";
    for (auto &it : bejegyzesek)
    {
        if ((it.get_path().find("City/Debrecen/Oktatás/Informatika/Programozás/DEIK/Prog1/Labor/Védés/") != std::string::npos) && (it.get_points()) && (!check_vedes(v_vec, it.get_name())))
            v_vec.insert(std::make_pair(it.get_name(),std::make_pair(1,it.get_points())));
        else if ((check_vedes(v_vec, it.get_name())) && (it.get_path().find("City/Debrecen/Oktatás/Informatika/Programozás/DEIK/Prog1/Labor/Védés/") != std::string::npos) && (it.get_points()))
            vedes_elem(v_vec, it.get_name(), it.get_points());
    }
}
void list_atlag(vedes_vec &v_vec)
{
    //std::sort(v_vec.begin(), v_vec.end());
    Comparator compFunctor = [](std::pair<std::string,std::pair<int,int>> elem1,std::pair<std::string,std::pair<int,int>> elem2)
            {
                std::pair<int,int> it = elem1.second;
                std::pair<int,int> jt = elem2.second;
                return it.first < jt.first;
            };
    std::set<std::pair<std::string,std::pair<int,int>>,Comparator> v_set(v_vec.begin(),v_vec.end(),compFunctor);
    //int sum = 0;
    //int csum = 0;
    for (std::pair<std::string,std::pair<int,int>> it : v_set)
    {
        std::pair<int,int> jt = it.second;
        std::cout << it.first << " " << (jt.second - jt.first) / jt.first<< std::endl;
        //sum += it.get_point();
        //csum += it.get_count();

        //sum = std::accumulate(v_vec.begin(), v_vec.end(), 0, [](int i, Vedes &o) { return i + o.get_point(); });
        //csum = std::accumulate(v_vec.begin(), v_vec.end(), 0, [](int i, Vedes &o) { return i + o.get_count(); });
    }
    //std::cout << (sum - csum) / csum << std::endl;
}

1 个答案:

答案 0 :(得分:2)

所以,正如所描述的那样here

template<
    class Key,
    class Compare = std::less<Key>,
    class Allocator = std::allocator<Key>
> class set;
  

std :: set是一个关联容器,包含一组排序为Key的唯一对象。

我清理了您的代码,并制作了Minimal, Complete, and Verifiable example

#include <iostream>
#include <map>
#include <set>

using point_pair = std::pair<int,int>;
using points_map = std::map<std::string, point_pair>;
using points_set_pair = std::pair<std::string, point_pair>;
auto compFunctor = [](const points_set_pair &elem1, const points_set_pair &elem2)
{
    return elem1.second.first < elem2.second.first;
};
using points_set = std::set<points_set_pair, decltype(compFunctor)>;

void list_average(const points_map &v_map)
{
    points_set v_set(v_map.begin(),v_map.end(),compFunctor);
    for (auto &elem : v_set)
    {
        const point_pair &jt = elem.second;
        std::cout << elem.first << " " << (jt.second - jt.first) / jt.first<< "\n";

    }
}

现在考虑主要的第一个版本

int main()
{
    points_map v_map = { {"foo", { 1, 2}}, {"bar", { 3, 4}}};

    list_average(v_map);
}

输出:

foo 1
bar 0

现在考虑main的第二个版本:

int main()
{
    points_map v_map = { {"foo", { 1, 2}}, {"bar", { 1, 4}}};

    list_average(v_map);
}

输出:

bar 3

看到问题?由于元素的.second.first都是1,后者替换第一个。它不是唯一的。这是std::set的缺点。

那么,那么呢?

请勿使用std::set,而是使用std::vectorstd::sort。例如:

#include <iostream>
#include <map>
#include <vector>
#include <algorithm>

using point_pair = std::pair<int,int>;
using points_map = std::map<std::string, point_pair>;
using string_point_pair = std::pair<std::string, point_pair>;
auto compFunctor = [](string_point_pair const &elem1, string_point_pair const &elem2)
{
    return 
        elem1.second.first != elem2.second.first?
        elem1.second.first < elem2.second.first:
        elem1.second.second < elem2.second.second;
};

void list_average(points_map const &v_map)
{
    std::vector<string_point_pair> v_vec(v_map.begin(),v_map.end());
    std::sort(v_vec.begin(), v_vec.end(), compFunctor);
    for (auto &elem : v_vec)
    {
        const point_pair &jt = elem.second;
        std::cout << elem.first << " " << (jt.second - jt.first) / jt.first<< "\n";

    }
}

int main()
{
    points_map v_map = { {"foo", { 1, 2}}, {"bar", { 1, 4}}, {"baz", { 2, 4}}};

    list_average(v_map);
}

输出:

foo 1
bar 3
baz 1

live demo