我正在使用QDir::entryList()
阅读目录内容。其中的文件名结构如下:
index_randomNumber.png
我需要按index
排序,这是Windows资源管理器对文件进行排序的方式,以便我得到
0_0815.png
1_4711.png
2_2063.png
...
而不是QDir::Name
给我的排序:
0_0815.png
10000_6661.png
10001_7401.png
...
在Qt中是否有内置的方法来实现这一目标,如果没有,那么实施它的正确位置是什么?
答案 0 :(得分:12)
在Qt 5.2之前,Qt没有自然排序实现,请参阅this feature request。
自Qt 5.2起,QCollator允许在启用numeric mode时进行自然排序。
答案 1 :(得分:10)
如果您想使用SeekableIterator
对QCollator
返回的条目列表中的条目进行排序,您可以使用QDir::entryList
对结果进行排序:
QCollator
根据std::sort()
的评论,std::sort
也可以直接用作std::sort(entryList.begin(), entryList.end(), collator);
的参数,替换lambda,所以最后一行变为:
user1 = client.feed('user', '1');
user1.token
答案 2 :(得分:2)
是的,这是可能的。
为了做到这一点,您需要在构建QDir
时指定标记LocaleAware。宾语。
QDir(const QString & path, const QString & nameFilter, SortFlags sort = SortFlags( Name | IgnoreCase ), Filters filters = AllEntries)
您也可以使用
QDir dir;
dir.setSorting(QDir::LocaleAware);
答案 3 :(得分:0)
这并不是对这个问题的答案,而是一些一般信息,这些信息使其他人受益,他们偶然发现了这种“自然排序”的方法。
首先,这是不可能的。 “正确的”自然排序取决于缺乏“真正的”人工智能的情况,而这实际上是不可能的。例如,如果我有一堆带有混合数字和字母的文件名,而这些文件名的某些部分恰好匹配[0-9a-f]
,那是十六进制数字吗? “ 1,500”是否与“ 1500”相同,还是“ 1”和“ 500”个数字? “ 2019/06/07”在“ 2019/07/06”之前还是之后? “ 1.21”和“ 1.5”又如何呢? (提示:最后一个取决于它们是十进制数字还是语义版本号。)
“解决”此问题需要加以限制;决定我们只处理特定情况,而超出这些范围的任何事情都会产生“错误”的答案。 (幸运的是,OP的问题似乎已经满足了通常的约束条件。)
也就是说,我相信QCollator
通常可以很好地工作(再次,因为它不是“真正的”工作,但是在通常接受的约束范围内可以成功)。在“自己的解决方案”部门中,还可以查看qtNaturalSort,我将其写为Qt-API对另一种算法(不是QCollator
)的改进。 (写时不支持不区分大小写,但欢迎使用补丁!)我竭尽全力使它“正确”地解析数字,甚至处理任意长度和非BMP数字的数字。
答案 4 :(得分:-1)
inline int findNumberPart(const QString& sIn)
{
QString s = "";
int i = 0;
bool isNum = false;
while (i < sIn.length())
{
if (isNum)
{
if (!sIn[i].isNumber())
break;
s += sIn[i];
}
else
{
if (sIn[i].isNumber())
s += sIn[i];
}
++i;
}
if (s == "")
return 0;
return s.toInt();
}
bool naturalSortCallback(const QString& s1, const QString& s2)
{
int idx1 = findNumberPart(s1);
int idx2 = findNumberPart(s2);
return (idx1 < idx2);
}
int main(int argc, char *argv[])
{
QCoreApplication a(argc, argv);
QDir dir(MYPATH);
QStringList list = dir.entryList(QDir::AllEntries | QDir::NoDotAndDotDot);
qSort(list.begin(), list.end(), naturalSortCallback);
foreach(QString s, list)
qDebug() << s << endl;
return a.exec();
}
答案 5 :(得分:-1)
Qt本身并不支持自然排序,但它可以很容易地实现。例如,这可用于对QStringList
:
struct naturalSortCompare {
inline bool isNumber(QChar c) {
return c >= '0' && c <= '9';
}
inline bool operator() (const QString& s1, const QString& s2) {
if (s1 == "" || s2 == "") return s1 < s2;
// Move to the first difference between the strings
int startIndex = -1;
int length = s1.length() > s2.length() ? s2.length() : s1.length();
for (int i = 0; i < length; i++) {
QChar c1 = s1[i];
QChar c2 = s2[i];
if (c1 != c2) {
startIndex = i;
break;
}
}
// If the strings are the same, exit now.
if (startIndex < 0) return s1 < s2;
// Now extract the numbers, if any, from the two strings.
QString sn1;
QString sn2;
bool done1 = false;
bool done2 = false;
length = s1.length() < s2.length() ? s2.length() : s1.length();
for (int i = startIndex; i < length; i++) {
if (!done1 && i < s1.length()) {
if (isNumber(s1[i])) {
sn1 += QString(s1[i]);
} else {
done1 = true;
}
}
if (!done2 && i < s2.length()) {
if (isNumber(s2[i])) {
sn2 += QString(s2[i]);
} else {
done2 = true;
}
}
if (done1 && done2) break;
}
// If none of the strings contain a number, use a regular comparison.
if (sn1 == "" && sn2 == "") return s1 < s2;
// If one of the strings doesn't contain a number at that position,
// we put the string without number first so that, for example,
// "example.bin" is before "example1.bin"
if (sn1 == "" && sn2 != "") return true;
if (sn1 != "" && sn2 == "") return false;
return sn1.toInt() < sn2.toInt();
}
};
然后使用就是:
std::sort(stringList.begin(), stringList.end(), naturalSortCompare());