从QStringList中删除子目录并仅保留其父目录

时间:2017-03-04 14:26:55

标签: c++ list qt for-loop qstring

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

/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 ++。

谢谢。

2 个答案:

答案 0 :(得分:0)

沿着这些方向行事(使用std::vectorstd::string代替QStringListQString;适应Qt课程留给读者练习:< / p>

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());

Demo

第二个想法,使用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

答案 1 :(得分:0)

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

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;
}