我都是在课堂上做这一切的。我有一份私人配对名单:
std::list<std::pair<std::string, size_t>> pokemons_;
我已向其传递某些值:
{("Pikachu", 25),
("Raticate", 20),
("Raticate", 20),
("Bulbasaur", 1),
("Pikachu", 25),
("Diglett", 50)};
现在我想通过调用我的类的公共删除函数来删除一对。
bool PokemonCollection::Remove(const std::string& name, size_t id) {};
我不明白如何在调用删除函数时比较字符串和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;
}
有一个非常简单的解决方案可以解决您的问题。
std::list
有一个功能remove_if
,它会为你做一切。请参阅此处。
请参阅以下代码作为示例:
#include <algorithm>
#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';
}
更多信息:
正如您可以在
remove_if
的 std::list
文档中阅读的那样,它需要按以下方式调用:
void remove_if( UnaryPredicate p );
您的问题可能是“UnaryPredicate”。我们可以读:
一元谓词,如果应删除元素则返回true。
并且,我们可以进一步阅读:
对于 T 类型(可能是 const)的每个参数 v,表达式 p(v) 必须可转换为 bool,无论值类别如何,并且不得修改 v。因此,不允许使用 T& 的参数类型,T 也不允许,除非T 移动相当于复制 (C++11 起)。
但这对你也没有多大帮助。基本上,谓词是一个极其简单的函数(对象)。
因此,
remove_if
将迭代std::list
中的所有元素,并将其称为“函数”。如果这个“函数”返回 true
,那么关联的 list
元素将被删除。
C++ 标准定义 Predicate 如下(25/7):
每当算法需要一个函数对象时,就会使用 Predicate 参数,该函数对象在应用于解引用相应迭代器的结果时返回一个可测试为 true 的值。换句话说,如果一个算法将谓词 pred 作为其参数,将 first 作为其迭代器参数,则它应该在构造 if (pred(*first)){...} 中正常工作。函数对象 pred 不应通过解引用迭代器应用任何非常量函数。该函数对象可以是指向函数的指针,也可以是具有适当函数调用运算符的类型的对象。
对于上述情况,我使用了 lambda 表达式 作为函数对象。这种机制在C++中被广泛使用。请阅读相关内容。
不幸的是
remove_if
不会返回任何值。这里确实有多种方法可以构建解决方案。
让我向您展示一种解决方案,仍然使用 lambda。
#include <algorithm>
#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';
}