Qt5中可以通过qSort接口,结合QLocale类和QCollator类,可以对中文,英文,数字进行排序,但默认排序顺序为数字、英文、中文,但如果需要中英文混合排序的话,需要另外封装方法实现。
这种方法就是先获取中文的首字母,然后在进行排序。
获取中文首字母
获取中文首字母需要用到编解码规则,下面有一份代码是我在网上找到的资料,能获取中文的首字母(GB2312)。
使用接口的时候切记不要忘记头文件哦
#include <QTextCodec>
接口(代码)部分:
static bool In(wchar_t start, wchar_t end, wchar_t code)
{
return (code >= start && code <= end) ? true : false;
}
static char convert(wchar_t n)
{
if (In(0xB0A1, 0xB0C4, n)) return 'a';
if (In(0XB0C5, 0XB2C0, n)) return 'b';
if (In(0xB2C1, 0xB4ED, n)) return 'c';
if (In(0xB4EE, 0xB6E9, n)) return 'd';
if (In(0xB6EA, 0xB7A1, n)) return 'e';
if (In(0xB7A2, 0xB8c0, n)) return 'f';
if (In(0xB8C1, 0xB9FD, n)) return 'g';
if (In(0xB9FE, 0xBBF6, n)) return 'h';
if (In(0xBBF7, 0xBFA5, n)) return 'j';
if (In(0xBFA6, 0xC0AB, n)) return 'k';
if (In(0xC0AC, 0xC2E7, n)) return 'l';
if (In(0xC2E8, 0xC4C2, n)) return 'm';
if (In(0xC4C3, 0xC5B5, n)) return 'n';
if (In(0xC5B6, 0xC5BD, n)) return 'o';
if (In(0xC5BE, 0xC6D9, n)) return 'p';
if (In(0xC6DA, 0xC8BA, n)) return 'q';
if (In(0xC8BB, 0xC8F5, n)) return 'r';
if (In(0xC8F6, 0xCBF0, n)) return 's';
if (In(0xCBFA, 0xCDD9, n)) return 't';
if (In(0xCDDA, 0xCEF3, n)) return 'w';
if (In(0xCEF4, 0xD188, n)) return 'x';
if (In(0xD1B9, 0xD4D0, n)) return 'y';
if (In(0xD4D1, 0xD7F9, n)) return 'z';
return '\0';
}
接口(代码)使用:
QTextCodec *codec4gbk = QTextCodec::codecForName("GBK"); //获取qt提供的gbk的解码器
QByteArray buf = codec4gbk->fromUnicode(str); //qt用的unicode,专程gbk
quint16 *array = new quint16[buf.size() + 1];
QString FirstWord;
// for (int i = 0, j = 0; i < buf1.size(); i++, j++) //循环多次查找,此处只需获取首字母
// {
if ((quint8)buf1[0] < 0x80)
{
FirstWord = str;
//continue;
}//gbk的第一个字节都大于0x81,所以小于0x80的都是符号,字母,数字etc
else
{
array[0] = (((quint8)buf[0]) << 8) + (quint8)buf[1]; //计算gbk编码
//i++;
FirstWord.append(convert(array[0])); //相当于查表,用gbk编码得到首拼音字母
}
// }
上面方法代码量有点过于复杂,我重新封装了一个接口,方便直接使用。
头文件
#include <QByteArray>
封装接口代码(GB2312):
static char getFirstWord(const QString &str)
{
QByteArray bArr = str.toLocal8Bit();
const char *p = bArr.data();
uint8_t firstByte = *p;
if (firstByte < 128)
{
return firstByte;
}
uint8_t secondByte = *(p + 1);
uint16_t word = 0;
word = firstByte << 8;
word |= secondByte;
if (word >= 0xB0A1 && word < 0xB0C4) return 'A';
if (word >= 0XB0C5 && word < 0XB2C0) return 'B';
if (word >= 0xB2C1 && word < 0xB4ED) return 'C';
if (word >= 0xB4EE && word < 0xB6E9) return 'D';
if (word >= 0xB6EA && word < 0xB7A1) return 'E';
if (word >= 0xB7A2 && word < 0xB8c0) return 'F';
if (word >= 0xB8C1 && word < 0xB9FD) return 'G';
if (word >= 0xB9FE && word < 0xBBF6) return 'H';
if (word >= 0xBBF7 && word < 0xBFA5) return 'J';
if (word >= 0xBFA6 && word < 0xC0AB) return 'K';
if (word >= 0xC0AC && word < 0xC2E7) return 'L';
if (word >= 0xC2E8 && word < 0xC4C2) return 'M';
if (word >= 0xC4C3 && word < 0xC5B5) return 'N';
if (word >= 0xC5B6 && word < 0xC5BD) return 'O';
if (word >= 0xC5BE && word < 0xC6D9) return 'P';
if (word >= 0xC6DA && word < 0xC8BA) return 'Q';
if (word >= 0xC8BB && word < 0xC8F5) return 'R';
if (word >= 0xC8F6 && word < 0xCBF0) return 'S';
if (word >= 0xCBFA && word < 0xCDD9) return 'T';
if (word >= 0xCDDA && word < 0xCEF3) return 'W';
if (word >= 0xCEF4 && word < 0xD188) return 'X';
if (word >= 0xD1B9 && word < 0xD4D0) return 'Y';
if (word >= 0xD4D1 && word < 0xD7F9) return 'Z';
return '#';
}
封装接口代码(unicode):
static char FirstLetter(const QString &str)
{
int ucHigh, ucLow;
int nCode;
QByteArray bArr = str.toLocal8Bit();
const char *p = bArr.data();
uint8_t firstByte = *p;
ucHigh = (int)(p[0] & 0xFF);
ucLow = (int)(p[1] & 0xFF);
if (ucHigh < 0xa1 || ucLow < 0xa1)
{
return firstByte;
}
nCode = (ucHigh - 0xa0) * 100 + ucLow - 0xa0;
if (nCode >= 1601 && nCode < 1637) return 'A';
if (nCode >= 1637 && nCode < 1833) return 'B';
if (nCode >= 1833 && nCode < 2078) return 'C';
if (nCode >= 2078 && nCode < 2274) return 'D';
if (nCode >= 2274 && nCode < 2302) return 'E';
if (nCode >= 2302 && nCode < 2433) return 'F';
if (nCode >= 2433 && nCode < 2594) return 'G';
if (nCode >= 2594 && nCode < 2787) return 'H';
if (nCode >= 2787 && nCode < 3106) return 'J';
if (nCode >= 3106 && nCode < 3212) return 'K';
if (nCode >= 3212 && nCode < 3472) return 'L';
if (nCode >= 3472 && nCode < 3635) return 'M';
if (nCode >= 3635 && nCode < 3722) return 'N';
if (nCode >= 3722 && nCode < 3730) return 'O';
if (nCode >= 3730 && nCode < 3858) return 'P';
if (nCode >= 3858 && nCode < 4027) return 'Q';
if (nCode >= 4027 && nCode < 4086) return 'R';
if (nCode >= 4086 && nCode < 4390) return 'S';
if (nCode >= 4390 && nCode < 4558) return 'T';
if (nCode >= 4558 && nCode < 4684) return 'W';
if (nCode >= 4684 && nCode < 4925) return 'X';
if (nCode >= 4925 && nCode < 5249) return 'Y';
if (nCode >= 5249 && nCode < 5590) return 'Z';
return '#';
}
至于通过Unihan字实现中文转换字母,由于代码量比较大,已上传到资源下载:
https://download.csdn.net/download/qq_36651243/11257140
排序部分(qSort)
QCollator类:能根据本地化的排序规则算法比较字符串
QLocale类:能在不同语言的数字及其字符串表示形式之间进行转换
使用的时候,记得加上头文件
#include <QLocale>
#include <QCollator>
排序代码部分:
qSort(m_listUserInfo.begin(), m_listUserInfo.end(), [=](auto p2, auto p1) {
QLocale loc(QLocale::Chinese, QLocale::China); //此处由于已经改成了英文比较(字母),因此语言和地区都可以选择英文/美国
QCollator qcol(loc);
int nResult = 0;
QString str1 = getFirstWord(p1->getNickName()); //获取首字母
QString str2 = getFirstWord(p2->getNickName());
nResult = qcol.compare(str1, str2);
return nResult > 0 ? true : false;
});
想更深了解QCollator类?
https://doc.qt.io/qt-5.9/qcollator.html
想更深了解QLocale类?
https://doc.qt.io/qt-5.9/qlocale.html