我正在嘗試撰寫一個遞回函式,它將檢查每個嵌套物件的偶數并回傳這些數字的最終總和。我正在努力除錯到目前為止的功能。
function nestedEvenSum(obj, sum = 0) {
for(const k in obj) {
if (obj[k].constructor === Object) {
return sum = nestedEvenSum(obj[k], sum);
}
if (typeof obj[k] === "number" && obj[k] % 2 === 0) {
sum = obj[k];
}
}
return sum;
}
const obj = {
a: 2,
c: {c: {c: 2}, cc: 'b', ccc: 5},
e: {e: {e: 2}, ee: 'car'}
}
console.log(nestedEvenSum(obj));
函式回傳8。它應該回傳6。
另外,我注意到它e完全忘記了物件,最后一個遞回呼叫的物件是{c: 2}.
uj5u.com熱心網友回復:
這展示了一個經典的遞回反模式:將結果 ( sum) 作為引數向下傳遞呼叫堆疊,同時還試圖將其作為結果向上傳遞,從而導致事態混亂和重復計算。
這是遞回的基本經驗法則:資料依賴項(用于計算結果的東西)是引數,結果是回傳值。
使sum框架本地化,然后在框架內累積,因為每個元素都是一個數字(樹搜索中的葉節點),或者它是一個應該遞回探索的子元素。不要return立即進入回圈,否則您會錯過一些孩子。
function nestedEvenSum(obj) {
let sum = 0;
for (const k in obj) {
if (obj[k].constructor === Object) {
sum = nestedEvenSum(obj[k]);
}
else if (typeof obj[k] === "number" && obj[k] % 2 === 0) {
sum = obj[k];
}
}
return sum;
}
const obj = {
a: 2,
c: {
c: {
c: 2
},
cc: 'b',
ccc: 5
},
e: {
e: {
e: 2
},
ee: 'car'
}
};
console.log(nestedEvenSum(obj));
請注意,此演算法忽略陣列。
% 2 === 0另請注意,由于謂詞,該函式的設計非常嚴格。您可能會考慮使用遍歷任何嵌套結構并回傳可以過濾的結果的陣列或生成器的函式,或者允許任意回呼謂詞執行過濾的函式。
單向資料流規則的一個例外是,有時您希望將結果累積到引數陣列中作為優化,而不是在回傳呼叫堆疊時回傳和合并多個陣列,但這不適用于此處.
uj5u.com熱心網友回復:
我想我想通了。
首先,如果你找到一個物件,你就會回傳,這意味著你會提前停下來,所以我洗掉了早期的“回傳”。
其次,如果你找到一個物件,你就是在重復計算,因為你傳遞了你已經擁有的總和,然后將它添加到你已經擁有的總和中。
看看這個,只有幾個小改動:
function nestedEvenSum(obj, sum = 0) {
for(const k in obj) {
if (obj[k].constructor === Object) {
sum = nestedEvenSum(obj[k], sum);
}
if (typeof obj[k] === "number" && obj[k] % 2 === 0) {
sum = obj[k];
}
}
return sum;
}
const obj = {
a: 2,
c: {c: {c: 2}, cc: 'b', ccc: 5},
e: {e: {e: 2}, ee: 'car'}
}
console.log(nestedEvenSum(obj));
uj5u.com熱心網友回復:
您需要洗掉第一個 return 陳述句。
要獲得更短的代碼,您可以使用條件陳述句。
這種方法確實保留了實際物件的總和,并且不會將總和交給嵌套級別。
僅尾呼叫優化(TCO)需要移交,因為用堆疊的遞回函式替換舊函式。實際上 TCO 是在 Javascript 中沒有得到廣泛支持...
function nestedEvenSum(obj) {
let sum = 0;
for (const k in obj) {
sum = obj[k] && typeof obj[k] === 'object'
? nestedEvenSum(obj[k])
: obj[k] % 2 === 0
? obj[k]
: 0;
}
return sum;
}
const obj = { a: 2, c: { c: { c: 2 }, cc: 'b', ccc: 5 }, e: { e: { e: 2 }, ee: 'car' } };
console.log(nestedEvenSum(obj));
uj5u.com熱心網友回復:
為什么不在一個簡單的深度過濾函式之上構建它呢?
const filterDeep = (p) => (o) =>
p (o) ? [o] : Object (o) === o ? Object .values (o) .flatMap ((v) => filterDeep (p) (v)) : []
const sum = (ns) => ns .reduce ((a, b) => a b, 0)
const nestedEvenSum = (o) =>
sum (filterDeep (n => typeof n == 'number' && n % 2 == 0) (o))
const obj = {a: 2, c: {c: {c: 2}, cc: 'b', ccc: 5}, e: {e: {e: 2}, ee: 'car', j: [8, 6, 7, 5, 3, 0, 9]}}
console .log (nestedEvenSum (obj))
這里filterDeep接受一個謂詞函式并回傳一個函式,該函式接受一個 Object 并收集所有與該謂詞匹配的(嵌套)元素。有了一個次要的sum輔助函式,我們現在可以nestedEvenSum以一種非常簡單的方式撰寫,并且可以將有用的輔助函式用于其他用途。
轉載請註明出處,本文鏈接:https://www.uj5u.com/gongcheng/495654.html
標籤:javascript 递归
上一篇:遞回DFS列印嵌套串列
