在C++中从向量中删除元素

3

我正在编写一个基于足球队名单的程序。每个球员都有一个球衣号码和评分。我正在尝试找出如何在用户输入球员球衣号码后删除该球员的评分和球衣号码。我定义了两个int向量,一个用于球员的球衣号码,另一个用于球员的评分。这是我目前为止的删除球员函数。不确定我做错了什么。

void delete_player()
    {
        int input;
        int vecSize = jersey.size();
        cout << "Enter a jersey number to delete: ";
        cin >> input;
        for (int i = 0; i < vecSize; i++)
        {
            if (input == jersey[i])
            {
                jersey.erase(jersey.begin() + i);
                rating.erase(rating.begin() + i);
            }

        }
    }
2个回答

4

看起来你在使用错误的工具。似乎你需要一个std :: map<jerseyNum,rating>。像这样:

 using jerseyNum = int;
 using rating = int;
 using playerMap = std::map<jerseyNum, rating>;
 playerMap Players;

然后,您可以通过以下方式将玩家添加到其中:
Players [ newJerseyNum ] = newRating;

您可以通过以下方式删除玩家:
auto foundPlayer = Players.find(jerseyToDelete);
if (foundPlayer != Players.end())
{
     Players.erase(foundPlayer);
}

非常抱歉,我对C++编程非常陌生,不知道如何实现您的建议。对于我的添加球员函数,我只是使用rating/jersey.push_back(input)将每个球衣号码和评分添加到它们各自的向量中。作为一个初学者,有没有更简单的方法使用vector.erase删除向量中特定元素的实例? - AlexCPSC
1
@AlexCPSC,一个映射使用输入来唯一确定输出。如果您编写Players[32] = "John",然后将print( Players[32] )打印到屏幕上,您将看到"John"打印到控制台。键"32"唯一对应于值"John"。 - Sean Pianka

4

无需编写循环以从向量中删除项。使用erase/remove惯用语:

void delete_player()
{
    int input;
    cout << "Enter a jersey number to delete: ";
    cin >> input;
    jersey.erase(std::remove(std::begin(jersey), std::end(jersey), input), jersey.end());
    rating.erase(std::remove(std::begin(rating), std::end(rating), input), rating.end());
}

基本上,std::remove 函数会返回一个迭代器指向要删除的“死”项(在向量末尾)。然后从此迭代器开始调用 vector::erase 直到 vector::end() 将这些死亡项删除。
一般来说,如果你发现自己正在编写循环或“手动编写”的代码,而这些代码似乎已经做了很多次(例如从容器中删除项),那么可能有一系列的STL算法函数可以完成这项工作。在这种情况下,std::remove 是算法函数。
如果你需要删除相应的 rating,那么应该使用 std::find:
void delete_player()
{
    int input;
    cout << "Enter a jersey number to delete: ";
    cin >> input;
    auto iter = std::find(std::begin(jersey), std::end(jersey), input);
    if (iter != std::end(jersey))
    {
       auto dist = std::distance(std::begin(jersey), iter);
       jersey.erase(std::begin(jersey) + dist);
       rating.erase(std::begin(rating) + dist);
    }
}
std::distance函数返回从begin()到由std::find返回的迭代器之间的“距离”。

但是,使用这种方法处理两个单独的向量存在风险。如果jerseyrating的大小不同,在从rating向量中删除元素时就会出现越界访问的风险。另一篇答案展示了使用std::map的更合适的容器。


坚实的建议和智慧。 - David C. Rankin
这样做是行不通的,因为用户必须将球衣号码作为输入输入,并从向量中删除具有该球衣号码和相应元素的评分向量。因此,如果一个球员例如拥有球衣号码12和评分5,而我在控制台中输入12,则相应的评分不会从评分向量中删除。 - AlexCPSC
1
@AlexCPSC 那么另一个答案确实是你应该使用的(一个 std::map)。如果你必须使用 vector,请查看我的编辑。此外,以你目前的方式使用 std::vector 是容易出错的,因为你需要确保 jerseyrating 向量具有相同的大小。 - PaulMcKenzie

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接