【发布时间】:2019-05-26 14:55:37
【问题描述】:
我有一个函数,给定一个文本块,应该删除所有标点符号,并使所有字母小写,最后,应该根据单字母密码将它们转换。下面的代码有效:
class Cipher {
public:
string keyword;
string decipheredText;
deque<string> encipheredAlphabet;
static bool is_punctuation (char c) {
return c == '.' || c == ',' || c == '!' || c == '\''|| c == '?' || c
== ' ';
}
string encipher(string text) {
Alphabet a;
encipheredAlphabet = a.cipherLetters(keyword);
text.erase( remove_if(text.begin(), text.end(), is_punctuation),
text.end() );
string::iterator it;
for (it = text.begin(); it != text.end(); it++) {
*it = tolower(*it);
// encipher text according to shift
}
return text;
}
};
问题是,它目前对字符串进行了两次遍历,一次删除标点符号,一次执行所有其他操作。这似乎效率低下,因为似乎所有转换都可以以某种方式通过字符串一次完成。有没有一种干净的方法可以将擦除删除习语与其他循环条件结合起来?
【问题讨论】:
-
当然。只需编写您自己的算法:
remove_if_tolowercase_otherwise。看看std::remove_if是如何实现的并进行调整。 -
这似乎效率低下 -- 分析代码。遍历一个容器
n次一次执行一次操作,或者一次执行n次操作,理论上复杂度是一样的。 -
是的,你是对的。我的意思是复杂性是相同的,但现实世界的效率可能不同。但这就是为什么在试图使循环“太优雅”以至于人们无法理解它在做什么之前,应该对代码进行分析。
-
代码可读性很重要,两个循环的可读性很强,因为它们执行两个不同的任务。您可以将
for循环替换为 std::transform。 -
第二遍看起来不像
for(auto &c : text)那样冗余和漂亮。