从对列表中删除一个对C++

oyxsuwqo  于 9个月前  发布在  其他
关注(0)|答案(2)|浏览(122)

我在课堂上都是这么做的。我有一个私人配对列表:

std::list<std::pair<std::string, size_t>> pokemons_;

字符串
我传递了一些值给它:

{("Pikachu", 25),
    ("Raticate", 20),
    ("Raticate", 20),
    ("Bulbasaur", 1),
    ("Pikachu", 25),
    ("Diglett", 50)};


现在我想通过调用类的公共remove函数来移除一个pair。

bool PokemonCollection::Remove(const std::string& name, size_t id) {};


我不明白在调用remove函数时如何比较字符串和id值:

collection.remove("Raticate", 20);


“集合是我的类的对象”
我已经实现了:

bool PokemonCollection::Remove(const std::string& name, size_t id) {
    bool found;
    string x;
    size_t  y;

    for (auto currentPair : pokemons_) {

        pair<string, size_t> currentpair = currentPair;
        x = currentpair.first;
        y = currentpair.second;

        pokemons_.erase(pokemons_.begin() + i)

        for (int i=0; i<pokemons_.size(); i++) {
             if (pokemons_[i].first == x && pokemons_[i].second == y) {
                 //pokemons_.erase(pokemons_.begin() + i);
                 cout<<"FOUND!!!!!!!!!!!!!!!";
                 found = true;
                 return true;
            }
            else {
                found = false;
            }
        }
    }
    return found;
}


但是我的这个删除函数给出了一些我不太理解的错误。
另外,在我使用 erase 函数的注解行上也有很多错误。我如何比较字符串和id,并将其从类的原始私有列表中删除?

我的功能

bool PokemonCollection::Remove(const std::string& name, size_t id) {

    bool found;
    //string x;
    //size_t y;

    pokemons_.remove_if([&](std::pair<std::string, size_t>& p) {
        return found = true and p.first==name and p.second==id;
    });

    if(found == true) {
        return true;
    }
    else {
        found = false;
    }
    return found;
}

yiytaume

yiytaume1#

有一个非常简单的方法可以解决你的问题。
std::list有一个函数remove_if,它将为你做一切。参见here
请看下面的代码作为例子:

#include <iostream>
#include <string>
#include <utility>
#include <list>

std::list<std::pair<std::string, size_t>> poke
        {{"Pikachu", 25}, 
        {"Raticate", 20}, 
        {"Raticate", 20}, 
        {"Bulbasaur", 1}, 
        {"Pikachu", 25}, 
        {"Diglett", 50}};

void remove(const std::string& s, size_t i) {
    
    poke.remove_if([&](std::pair<std::string, size_t>& p){return p.first== s and p.second==i;});
}

int main() {
    remove("Raticate", 20);

    for (const auto& [s,i] : poke) 
        std::cout << s << '\t' << i <<'\n';
}

字符串
更多信息:
正如你在std::listremove_if文档中所读到的,它需要如下调用:
void remove_if(unaryPredicate);
你的问题可能是“UnaryPredicate”。我们可以读到:
一元 predicate ,如果元素应该被删除,则返回true。
我们可以进一步阅读:
表达式p(v)必须对每个类型为T(可能是const)的参数v可转换为bool,而不管值的类别,并且不能修改v。因此,T&的参数类型是不允许的,T也是不允许的,除非T的移动等价于复制(C11起)。
但这也不会对你有太大帮助,基本上,一个 predicate 是一个函数(对象)。
因此,remove_if将遍历std::list中的所有元素并调用此“函数”。如果此“函数”返回true,则将删除关联的list-元素。
C
标准对Predicate的定义如下(25/7):
Predicate参数用于当一个算法期望一个函数对象,当应用于解引用的结果时,对应的迭代器返回一个可测试为true的值。换句话说,如果一个算法将Predicate pred作为其参数,并将first作为其迭代器参数,它应该在构造中正确工作,如果(pred(*first)){...}。函数对象pred不应用任何非-这个函数对象可以是一个指向函数的指针,或者是一个具有适当函数调用操作符的类型的对象。
在上面的例子中,我使用了一个lambda expression作为函数对象。这种机制在C++中被广泛使用。请阅读有关内容。
不幸的是,remove_if不会返回任何值。这里有几种构建解决方案的方法。
让我给你们看一个解决方案,仍然使用lambda。

#include <iostream>
#include <string>
#include <utility>
#include <list>

std::list<std::pair<std::string, size_t>> poke
{ {"Pikachu", 25},
{"Raticate", 20},
{"Raticate", 20},
{"Bulbasaur", 1},
{"Pikachu", 25},
{"Diglett", 50} };

bool remove(const std::string& s, size_t i) {

    bool found = false;
    poke.remove_if([&](std::pair<std::string, size_t>& p) {bool rv = (p.first == s and p.second == i); if (rv) found = true; return rv; });
    return found;
}

int main() {
    if (remove("Raticate", 20))
        std::cout << "\nFound\n\n";
    else
        std::cout << "\nNot Found\n\n";

    for (const auto& [s, i] : poke)
        std::cout << s << '\t' << i << '\n';
}

e0bqpujr

e0bqpujr2#

它可以比A M的解决方案更简单。std::pair<>附带comparison operators,因此您不需要自定义函数来检查列表中的元素是否等于给定的对:

void remove(const std::string& s, size_t i) {
    poke.remove({s, i});
}

字符串
从C++20开始,std::listremove()remove_if()返回被删除的元素的数量。如果你需要与早期版本兼容,你可以在调用remove()之前和之后检查poke.size()的结果,看看列表的大小是否改变了。

相关问题