我正在处理行列表,我需要计算开头出现的哈希值。
# item 1
## item 1, 1
## item 1, 2
# item 2
以此类推。
如果每行都是QString,如何返回字符串开头出现的哈希数?
QString s("### foo # bar ");
int numberOfHashes = s.count("#"); // Answer should be 3, not 4
答案 0 :(得分:4)
在这里,我使用标准算法find_if_not
来获得第一个非哈希字符的迭代器。然后,我返回从字符串开头到该迭代器的距离。
int number_of_hashes(QString const& s)
{
auto it = std::find_if_not(std::begin(s), std::end(s), [](QChar c){return c == '#';});
return std::distance(std::begin(s), it);
}
编辑:find_if_not
函数仅采用一元谓词,而不采用值,因此您必须传递lambda谓词。
答案 1 :(得分:3)
琐碎:
int number_of_hashes(const QString &s) {
int i, l = s.size();
for(i = 0; i < l && s[i] == '#'; ++i);
return i;
}
在其他语言(大多数是解释性语言)中,您必须担心字符迭代的速度较慢,并将所有内容委派给库函数(通常使用C语言编写)。在C ++中,迭代在性能上是非常好的,因此扎实的for
循环就可以了。
只是为了好玩,我做了a small benchmark并将这种简单的方法与OP中的QRegularExpression
方法进行了比较,可能还缓存了RE对象。
#include <QCoreApplication>
#include <QString>
#include <vector>
#include <QElapsedTimer>
#include <stdlib.h>
#include <iostream>
#include <QRegularExpression>
int number_of_hashes(const QString &s) {
int i, l = s.size();
for(i = 0; i < l && s[i] == '#'; ++i);
return i;
}
int main(int argc, char *argv[])
{
QCoreApplication a(argc, argv);
const int count = 100000;
std::vector<QString> ss;
for(int i = 0; i < 100; ++i) ss.push_back(QString(rand() % 10, '#') + " foo ## bar ###");
QElapsedTimer t;
t.start();
unsigned tot = 0;
for(int i = 0; i < count; ++i) {
for(const QString &s: ss) tot += number_of_hashes(s);
}
std::cerr<<"plain loop: "<<t.elapsed()*1000./count<<" ns\n";
t.restart();
for(int i = 0; i < count; ++i) {
for(const QString &s: ss) tot += QRegularExpression("^[#]*").match(s).capturedLength();
}
std::cerr<<"QRegularExpression, rebuilt every time: "<<t.elapsed()*1000./count<<" ns\n";
QRegularExpression re("^[#]*");
t.restart();
for(int i = 0; i < count; ++i) {
for(const QString &s: ss) tot += re.match(s).capturedLength();
}
std::cerr<<"QRegularExpression, cached: "<<t.elapsed()*1000./count<<" ns\n";
return tot;
}
正如预期的那样,基于QRegularExpression
的计算机要慢两个数量级:
plain loop: 0.7 ns
QRegularExpression, rebuilt every time: 75.66 ns
QRegularExpression, cached: 24.5 ns
答案 2 :(得分:3)
int numberOfHashes = 0;
int size = s.size();
QChar ch('#');
for(int i = 0; (i < size) && (s[i] == ch); ++i) {
++numberOfHashes;
}
答案 3 :(得分:3)
没有 for循环的解决方案:
QString s("### foo # bar ");
int numberOfHashes = QRegularExpression("^[#]*").match(s).capturedLength();
答案 4 :(得分:2)
另一种方式:
int beginsWithCount(const QString &s, const QChar c) {
int n = 0;
for (auto ch : s)
if (c == ch) n++; else break;
return n;
}
答案 5 :(得分:1)
使用QString::indexOf(..)
的Qt方法:
QString s("### foo # bar ");
int numHashes = 0;
while ((numHashes = s.indexOf("#", numHashes)) == numHashes) {
++numHashes;
} // numHashes == 3
int QString::indexOf(const QString &str, int from = 0, Qt::CaseSensitivity cs = Qt::CaseSensitive) const
返回字符串
str
在此字符串中首次出现的索引位置,从索引位置from
开始向前搜索。如果找不到-1
,则返回str
。
从索引0
开始,在字符串s
中搜索#
的第一个匹配项,然后使用谓词测试此匹配项是否在索引0
上。如果未终止,则继续执行索引1
,依此类推。
但是,这不会使最终的完整字符串搜索短路。如果在预期的最终位置未找到哈希值,则在最终失败的谓词检查之前,将对字符串进行完全搜索(或直到在错误位置的第一个哈希值为止)。