假設我在一個類中有兩個函式:
vector<int> getAllPossibleNumbers() {
vector<int> nums;
for (int i=0; i < MAX; i )
if (isAPossibleNumber(i))
nums.push_back(i);
return nums;
}
bool hasAtLeastOnePossibleNumber() {
for (int i=0; i < MAX; i)
if (isAPossibleNumber(i))
return true;
return false;
}
我可以將第二個函式重寫為
bool hasAtLeastOnePossibleNumber() {
return getAllPossibleNumbers().size() > 0;
}
但很明顯,特別是對于非常高的 MAX 數,第一個如何更有效。
那么,我怎樣才能避免這種代碼重復呢?
我更喜歡通用解決方案,它可以處理更復雜的函式,并且可以使用 C 11 進行編譯。
uj5u.com熱心網友回復:
一種選擇是將大部分邏輯移動到第三個函式中,并回呼提供數字的外部函式。回呼的結果可以用來判斷是否繼續回圈:
template <typename Callback>
void checkNumbers(Callback callback)
{
for (int i=0; i < MAX; i )
{
if (isAPossibleNumber(i))
{
if (!callback(i))
{
break;
}
}
}
}
std::vector<int> getAllPossibleNumbers() {
std::vector<int> nums;
checkNumbers([&](int i){ nums.push_back(i); return true; });
return nums;
}
bool hasAtLeastOnePossibleNumber() {
bool result = false;
checkNumbers([&](int i){ result = true; return false; });
return result;
}
額外的功能應該被現代編譯器優化掉。
uj5u.com熱心網友回復:
我不會費心去重構代碼,因為重復并不那么激烈。這兩個函式確實做不同的事情。但是,如果您撰寫一個只回傳一個的函式int:
const int MAX = 100;
bool isAPossibleNumber(int i){ return true;}
int getNextPossibleNumber(int start=0,int stop = MAX) {
for (int i=0; i < stop; i ) {
if (isAPossibleNumber(i)) return i;
}
return stop;
}
然后其中一個功能將簡單而簡短
bool hasAtLeastOnePossibleNumber() {
return getNextPossibleNumber(0,MAX) != MAX;
}
而另一個變得更加冗長
std::vector<int> getAllPossibleNumbers() {
std::vector<int> nums;
int start = 0;
while (start < MAX) {
auto i = getNextPossibleNumber(start);
if (i != MAX) nums.push_back(i);
start = i 1;
}
return nums;
}
請注意,總的來說這是更多代碼,因此需要權衡。如果您在getNextPossibleNumber其他地方也不需要,我可能會保留您的代碼。
另請注意,雖然這會稍微減少代碼重復,但不會減少您執行以下操作時需要完成的作業量:
if (hasPossibleNumber()) {
auto vec = getAllPossibleNumbers();
}
在最壞的情況下,唯一可能的數字是MAX-1并且兩個函式都將迭代整個范圍。與其讓兩個函式都完成作業,不如快取結果并在再次呼叫其中一個函式時重用它。
uj5u.com熱心網友回復:
您實際上沒有任何代碼重復。它看起來就像你做的那樣,因為你已經使用基于索引的 for 回圈來實作不同的演算法。如果你到處都寫這樣的回圈,看起來你有重復的代碼。
你應該做的是使用適當的演算法
vector<int> getAllPossibleNumbers()
{
vector<int> nums;
std::ranges::copy_if(std::views::iota(0, MAX),
std::back_inserter(nums),
isAPossibleNumber);
return nums;
}
bool hasAtLeastOnePossibleNumber()
{
return std::ranges::any_of(std::views::iota(0, MAX),
isAPossibleNumber);
}
現在沒有什么可以洗掉重復資料了。
*這是 C 20 代碼,但您可以在舊版本中執行幾乎相同的操作。
轉載請註明出處,本文鏈接:https://www.uj5u.com/qianduan/408779.html
標籤:
上一篇:Qml/Qtc :當底層Qtc ListModel發生變化時如何自動更新QmlListView中的專案?
下一篇:C 釋放嵌套容器和物件的記憶體
