我的问题非常简单,但我无法想到一个优雅的解决方案
在我的应用程序中,从用户输入中收集了一堆相对路径(它们实际上并不存在于文件系统中)。
举个例子:
这些收集在一个QList中(其中包含指向具有路径作为QString成员的类实例的指针),但容器对我来说并不重要。
理想的结果是将列表以有序的形式存在,文件上的目录(正如我们从大多数文件管理器中使用的那样),基本上就像你将树真实的文件系统一样。
显然,基于正常字符串的排序不起作用,但是对这样的列表进行排序的最优雅/最简单的方法是什么?
答案 0 :(得分:1)
我会为内置排序编写自定义comparator函数。这样的事情可能有用:
auto cmp = [](const string& lhs, const string& rhs) {
int len = min(lhs.size(), rhs.size());
for (int i = 0; i < len; i++) {
if (lhs[i] = rhs[i]) continue;
// check if there is a '/' starting from position i in both paths
// put directory first (if only one is a directory)
// or return lhs[i] < rhs[i]
};
完成此代码应该相当容易, 然后
sort(begin(paths), end(paths), cmp);
请注意,我正在使用c ++ 11
答案 1 :(得分:1)
退后一步,花一点时间用简单的英语总结您想要的分类标准:
目录排在第一位,文件排在第二位。
目录按字母顺序排序,文件按字母顺序排序。
现在,一旦你的逻辑被简化为这种简单直接的定义,只需将这个逻辑直接转换为C ++代码。
首先,将每个字符串转换为单个值0或1,表示字符串是否具有路径名组件。
排序。然后,如果两个字符串的值相等,则像往常一样对字符串本身进行排序。简单:
std::sort(container.begin(),
container.end(),
[]
(const QString &a,
const QString &b)
{
// Compute whether a or b is a subdirectory, representing
// each as:
//
// 0: directory
// 1: file
int a_hier=a.contains('/') ? 0:1;
int b_hier=b.contains('/') ? 0:1;
if (a_hier != b_hier)
return a_hier < b_hier;
return a < b;
});
这是您基本的初步方法。如果有必要,可以调整这个以对目录的路径名进行略微不同的排序(因为路径名中的/
组件参与相对排序顺序,您可能想要也可能不想要,这在您的问题中不清楚)。