提问者:小点点

将std::map转换为有序的std::vector


我有一个std::map,它存储了一个字符串和一个类,我想根据类属性的值创建一个有序向量。 但是,当我在向量上迭代时,没有打印任何内容。 到目前为止,我的代码是这样的,编译器没有看到错误:

void Championship::orderTeams(std::vector<std::pair<std::string, class Team> > vect, std::map<std::string, class Team>& map) {
    for (auto const& entry : map)
    {
        if (vect.empty()) { //check if vector is empty and add the first pair
            vect.push_back(std::make_pair(entry.first, entry.second));
            continue;
        }

        for (auto pos = vect.begin(); pos != vect.end(); ++pos) {
            if(entry.second.points > pos->second.points){
                vect.insert(pos, std::make_pair(entry.first, entry.second));

            }else if (pos==vect.end()){
                //vect.insert(pos, std::make_pair(entry.first, entry.second)); //wanted to check if there's a differance between insert and push_back
                vect.push_back(std::make_pair(entry.first, entry.second));
            }
        }
    }
}

team只包含3个公共int值(pointgoalstakengoalsgived),构造函数和解构函数。

对的向量称为teamordered,我使用以下方式打印:

    for (const auto & team : teamOrdered){
        std::cout<<team.first<<" "<<team.second.points<<" "<<team.second.goalsScored<<" "<<team.second.goalsTaken<<std::endl;
    }

共2个答案

匿名用户

您的代码中有一些问题。 首先,您没有得到任何输出的原因是,vector是按值传入的; 因此,函数内部对vect的任何更改都将丢失。 您希望通过引用传递它。 您还可以通过const引用传入映射,因为您不需要更改映射。

最重要的是,您的排序方法实际上并不起作用。 考虑内部for-loop的条件,pos!=vect.end(); 但是,您有一个else if,它是pos==vect.end(),这简直是不可能的。 此外,即使在添加元素之后,您仍然试图将其添加到vect中,而迭代器可能无效(插入到vector中可能导致迭代器无效)。

下面是您的代码的一个工作示例:

void Championship::orderTeams(std::vector<std::pair<std::string, Team>> &vect, const std::map<std::string, Team>& map) {
    for (auto const& entry : map)
    {
        if (vect.empty()) { //check if vector is empty and add the first pair
            vect.push_back(std::make_pair(entry.first, entry.second));
            continue;
        }

        bool added = false;
        for (auto pos = vect.begin(); pos != vect.end(); ++pos) {
            if(entry.second.points > pos->second.points){
                vect.insert(pos, std::make_pair(entry.first, entry.second));
                added = true;
                break;
            }
        }
        if (!added){
            vect.push_back(std::make_pair(entry.first, entry.second));
        }
    }
}

这也可以简化,使用algorithy头中的std::sort,您可以返回一个向量,而不是接受一个向量。

std::vector<std::pair<std::string, Team>> orderTeams2( const std::map<std::string, Team>& map) {
    std::vector<std::pair<std::string, Team>> vect = { map.begin(), map.end() };
    std::sort( vect.begin(), vect.end(), []( auto &left, auto &right ) {
        return left.second.points > right.second.points;
    });
    return vect;
}

匿名用户

正如其他人所指出的,没有任何东西为您打印,因为您是按值传递向量的。 通过引用传递它或返回向量。

此外,还可以使用std::sort和谓词进行排序。 下面是一个可行的解决方案:

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

class Team {
public:
    int points;
    int goalsTaken;
    int goalsGiven;
};

void orderTeams(std::vector<std::pair<std::string, class Team> >& vect, std::map<std::string, class Team>& map) {

        for(auto currentIterator = map.begin(); currentIterator != map.end(); ++currentIterator) {
            vect.emplace_back(currentIterator->first, currentIterator->second);
        }

        std::sort(vect.begin(), vect.end(),
            [](const std::pair<std::string, class Team>& item1, const std::pair<std::string, class Team>& item2) -> bool { return item1.second.points > item2.second.points; });
}

int main()
{
    std::vector< std::pair<std::string, class Team>> teamOrdered;
    std::map<std::string, class Team> map;
    map.emplace(std::string("4"), Team{ 4, 4, 4 });
    map.emplace(std::string("2"), Team{ 2, 2, 2});
    map.emplace(std::string("1"), Team{ 1, 1, 1 });
    map.emplace(std::string("3"), Team{ 3, 3, 3});
    orderTeams(teamOrdered, map);


    for(const auto& team : teamOrdered) {
        std::cout << team.first << " " << team.second.points << " " << team.second.goalsGiven << " " << team.second.goalsTaken << std::endl;
    }
}