如何使用迭代器有条件地从列表中删除元素?
How to conditionally remove an element from a list using an iterator?
问题:
我正在编写一个简单的文件管理器应用程序。在这个程序中我有一个 "Directory" class:
class Directory
{
public:
Directory(string address, string directoryname)
{
this->path = address;
this->name = directoryname;
}
string GetFullPath(){ return path == "/" ? path + name : path + "/" + name; }
string path;
string name;
string user;
};
和一个 linked 目录对象列表:
list<Directory*> DirectoryList;
我想在linux中执行"rm -r directorypath"
shell命令,所以我需要浏览列表并删除"directorypath"目录及其所有子目录-目录。问题是我不知道如何浏览 link 列表并删除所有父目录为 "directorypath" 的目录。我试过这两种方法:
方法一:
此方法遇到运行时错误,因为它在第一次删除后无法再访问列表。
for (auto address : DirectoryList)
if (address->GetFullPath() == directorypath)
{
for (auto subdirectory : DirectoryList)
if (subdirectory ->path == address->GetFullPath())
DirectoryList.remove(subdirectory );
}
方法二:
for (auto address : DirectoryList)
if (address->GetFullPath() == directorypath)
{
for (auto it = DirectoryList.begin(); it != DirectoryList.end();)
it = DirectoryList.erase(it);
return true;
}
此方法即使在删除后也可以完美访问所有元素,但我不知道如何使用迭代器检查此 if 条件 it
:
if (subdirectory ->path == address->GetFullPath())
您的方法 1 失败了,因为 std::list.remove(val)
删除了您的列表中比较等于 val 的所有元素。你调用一次就完成了。 for()
循环不应该存在,这不是它的预期使用方式。很好的例子是 here.
请注意,此方法将修改您的容器及其大小。你需要在这里小心并确保你的迭代器在调用 erase
后仍然有效。我的直觉是迭代器确实失效了,这就是你出错的原因。
您的方法 2 看起来几乎没问题。首先,fallow niceguy 的建议检查条件:
if ((*it).path == address->GetFullPath())
现在,请记住擦除 it
会将迭代器更新为指向您删除的迭代器之后的位置。这算作迭代器的一次更新 it
。它将在 for
循环中进一步更新,但这不是您想要的(即每次迭代两次更新意味着您将跳过一些元素)。你可以尝试这样的事情:
auto it = DirectoryList.begin()
while (it != DirectoryList.end())
{
if ((*it).path == address->GetFullPath())
DirectoryList.erase(it);
}
问题:
我正在编写一个简单的文件管理器应用程序。在这个程序中我有一个 "Directory" class:
class Directory
{
public:
Directory(string address, string directoryname)
{
this->path = address;
this->name = directoryname;
}
string GetFullPath(){ return path == "/" ? path + name : path + "/" + name; }
string path;
string name;
string user;
};
和一个 linked 目录对象列表:
list<Directory*> DirectoryList;
我想在linux中执行"rm -r directorypath"
shell命令,所以我需要浏览列表并删除"directorypath"目录及其所有子目录-目录。问题是我不知道如何浏览 link 列表并删除所有父目录为 "directorypath" 的目录。我试过这两种方法:
方法一:
此方法遇到运行时错误,因为它在第一次删除后无法再访问列表。
for (auto address : DirectoryList)
if (address->GetFullPath() == directorypath)
{
for (auto subdirectory : DirectoryList)
if (subdirectory ->path == address->GetFullPath())
DirectoryList.remove(subdirectory );
}
方法二:
for (auto address : DirectoryList)
if (address->GetFullPath() == directorypath)
{
for (auto it = DirectoryList.begin(); it != DirectoryList.end();)
it = DirectoryList.erase(it);
return true;
}
此方法即使在删除后也可以完美访问所有元素,但我不知道如何使用迭代器检查此 if 条件 it
:
if (subdirectory ->path == address->GetFullPath())
您的方法 1 失败了,因为 std::list.remove(val)
删除了您的列表中比较等于 val 的所有元素。你调用一次就完成了。 for()
循环不应该存在,这不是它的预期使用方式。很好的例子是 here.
请注意,此方法将修改您的容器及其大小。你需要在这里小心并确保你的迭代器在调用 erase
后仍然有效。我的直觉是迭代器确实失效了,这就是你出错的原因。
您的方法 2 看起来几乎没问题。首先,fallow niceguy 的建议检查条件:
if ((*it).path == address->GetFullPath())
现在,请记住擦除 it
会将迭代器更新为指向您删除的迭代器之后的位置。这算作迭代器的一次更新 it
。它将在 for
循环中进一步更新,但这不是您想要的(即每次迭代两次更新意味着您将跳过一些元素)。你可以尝试这样的事情:
auto it = DirectoryList.begin()
while (it != DirectoryList.end())
{
if ((*it).path == address->GetFullPath())
DirectoryList.erase(it);
}