我有一個命令串列,如果用戶輸入,它將呼叫單獨的函式。與一位朋友交談時,他說我應該使用 switch,這樣可以更快、更容易地閱讀“if、else if、else”陳述句。
在檢查如何實作這一點時,我意識到我無法做到,因為輸入是一個字串,并且要讓開關作業,我需要將它轉換為一個列舉,似乎我擁有的最直接的選擇是映射每個選項如下所示。
標題
enum class input
{
min,
max,
avg,
count,
stdev,
sum,
var,
pow
};
map<string, input> inMap
{
{ "min", input::min },
{ "max", input::max },
{ "avg", input::avg },
{ "count", input::count },
{ "stdev", input::stdev },
{ "sum", input::sum },
{ "var", input::var },
{ "pow", input::pow }
};
enum在我不必映射每個值的情況下,是否有更易于使用的選項?這非常耗時,目前我沒有看到任何好處。
.cpp 檔案
void test::processInput(vector<string> input) {
switch (inMap[input[0]]) {
case inMap::min:
MIN(input);
break;
case inMap::max:
MAX(input);
break;
case inMap::avg:
AVG(input);
break;
case inMap::count:
COUNT(input);
break;
case inMap::stdev:
STDEV(input);
break;
case inMap::sum:
SUM(input);
break;
case inMap::var:
VAR(input);
break;
case inMap::pow:
POW(input);
break;
default:
std::cout << "Error, input not found" << std::endl;
}
}
我讀了一些關于散列值的帖子,這是一個好的選擇嗎?此時繼續使用 if、else if、else 不是更好嗎?
謝謝!
uj5u.com熱心網友回復:
為什么沒有要運行的字串映射。
然后你不需要轉換為列舉。
using Action = void(std::vector<std::string>);
using ActionFunc = std::function<Action>;
using ActionMap = std::map<std::string, ActionFunc>;
void MIN(std::vector<std::string>){}
... etc
ActionMap inMap
{
{ "min", MIN },
{ "max", MAX },
{ "avg", AVG },
{ "count", COUNT },
{ "stdev", STDDEV },
{ "sum", SUM },
{ "var", VAR },
{ "pow", POW }
};
void test::processInput(std::vector<std::string> input) // May want a ref here.
{
auto find = inMap.find(input[0]);
if (find == inMap.end()) {
std::cout << "Error, input not found" << std::endl;
return;
}
find->second(input);
}
uj5u.com熱心網友回復:
無論哪種方式,您都在進行許多字串比較,并且字串比較很慢。
當您執行 if/else 時,如果您有 n 個目標字串,您平均會進行 n/2 比較。所以 4 比較了 8 個關鍵字。
當您執行 amap時,這將減少為 log2(n) 比較 - 因此 3 比較 8 個條目。哦,還有一個額外的向后比較以檢查值是否等于索引。如果它既不小也不大,那么它一定是相等的。
鑒于地圖代碼更復雜,如您所見,您不會贏。使用(許多)更多關鍵字來檢查,您將獲得好處。
如果使用unordered_map,則字串將轉換為整數散列值,并有效地用于直接查找答案。但是,計算哈希可能是一個緩慢的程序,并且將進行最終比較以檢查找到的值是否完全匹配。為所有關鍵字生成散列的設定成本也更高。在這種特殊情況下,您可以撰寫自己的散列函式,它只需要前 2 個字符,并且可能會縮小范圍,這會比默認的字串散列函式快一些。
最后一種選擇是逐個字符查找。如果第一個字符是“m”,那么您立即將檢查減少到 2 個選項。's' 提供 2 個其他選項,依此類推。對于像這樣的小型資料集,只需執行第一個字符過濾器就會有所作為,執行第二個字符會為您提供唯一檢查。這些是簡單的字符比較,而不是整個字串比較,快得多!
沒有簡單的 stdlib 資料結構可以幫助您解決這個問題。您可以將其寫成 2 級嵌套 case 陳述句:
switch (input[0][0])
{
case 'm':
switch (input[0][1])
{
case 'i':
if (input[0].compare("min")==0) return MIN;
return NO_MATCH;
case 'a':
if (input[0].compare("max")==0) return MAX;
return NO_MATCH;
}
return NO_MATCH;
case 's':
switch(input[0][1])
{
case 't':
case 'u':
}
... etc
(作為讀者練習,有一個版本的 string::compare() 會跳過你已經比較過的字符)
您可以構建自己的樹結構來表示此單詞查找。如果您添加跳過樹中多個字母的功能,您可以生成相當有效的字串字典查找,其成本僅比單個字串比較多一點。
另一種選擇是,使用字串/目標對的排序向量,您可以執行自定義二進制截斷函式,該函式利用知道仍在搜索范圍內的所有字串具有相同的首字母,并且不再需要比較. 在這種情況下,它不會有太大的區別,但是有數百個關鍵字,這將比手動 case 陳述句更易于維護。
但最后,大多數關鍵字檢測代碼使用 .com 提供的簡單哈希表足夠快unordered_map。
轉載請註明出處,本文鏈接:https://www.uj5u.com/ruanti/488653.html
