从QStringList中删除子目录,仅保留父母的目录

Remove Subdirectories from a QStringList and only keep their parents directories

本文关键字:父母 保留 QStringList 删除 子目录      更新时间:2023-10-16

我已经有目录路径的列表。例如:

/home/aar/las
/home/aar/las/pes
/home/aar/las/fmp
/home/aar/.thumbnails
/home/aar/.thumbnails/normal
/home/aar/yfolder
/home/aar/.kde
/home/aar/.kde/share
/home/aar/.kde/share/config
/home/aar/.kde/share/apps
/home/aar/.kde/share/apps/okular

我想删除所有子目录并仅保留父母。

为此,我使用了此代码正常:

QStringList RemoveSubFolders_KeepParentFolders(QStringList FoldersList)
{
    QStringList FoldersList_First = FoldersList;
    QStringList FoldersList_Second = FoldersList;
    QStringList ToDelete;
    foreach (QString TheFolder_First, FoldersList_First) {
        foreach (QString TheFolder_Second, FoldersList_Second) {
            if (TheFolder_Second.startsWith(TheFolder_First) && TheFolder_First.toLower() != TheFolder_Second.toLower())
                ToDelete.append(TheFolder_Second);
        }
    }
    QStringListIterator i(ToDelete);
     while(i.hasNext()){
       FoldersList.removeAll(i.next());
     }
     return FoldersList;  //return list without subfolders
}

结果是:

/home/aar/las
/home/aar/.thumbnails
/home/aar/yfolder
/home/aar/.kde

====================================================================

问题:

事件,我认为这不是大列表的最佳和最快的方法。

有没有最好的方法来完成这项工作?

nb:

  • 我不在乎Windows或Ubunutu。
  • 我使用QT 5.8 C 。

谢谢。

这是一个黑客:保留其中最小/的路径

int pathDepth(const QString& path)
{
    return std::count_if(path.begin(), path.end(), [](QChar c) { return c == '/'; });
}
QStringList getParentFolders(const QStringList& folderList)
{
    QStringList ret;
    int minDepth = pathDepth(*std::min_element(folderList.begin(), folderList.end(),
        [](const QString& a, const QString& b){ return pathDepth(a) < pathDepth(b); }));
    foreach (QString path, folderList)
        if (pathDepth(path) == minDepth)
            ret << path;
    return ret;
}

沿这些行(使用std::vectorstd::string代替QStringListQString;适应QT类是读者的练习):

std::vector<std::string> v;  // populated with directory paths
std::sort(v.begin(), v.end());
std::string root;
auto erase_from = std::unique(v.begin(), v.end(),
  [&root](const std::string& a, const std::string& b) {
    if (root.empty() || a.size() < root.size() || a.compare(0, root.size(), root) != 0) {
      root = a;
    }
    return (b.size() >= root.size() && b.compare(0, root.size(), root) == 0);
  }
);
v.erase(erase_from, v.end());

演示


第二个思考,使用std::remove_if将更简单,更高效:

std::vector<std::string> v;  // populated with directory paths
std::sort(v.begin(), v.end());
std::string root;
auto erase_from = std::remove_if(v.begin(), v.end(),
  [&root](const std::string& dir) {
    if (root.empty() || dir.size() < root.size() ||
        dir.compare(0, root.size(), root) != 0) {
      root = dir;
      return false;
    }
    return true;
  }
);
v.erase(erase_from, v.end())

demo