我在這里有一個問題,我正在嘗試創建一個函式來總結深度嵌套陣列中的所有整數,但它沒有通過單元測驗,這意味著有些事情是不正確的。這是我的功能:
export const arraySum = (arr) => {
let sum = 0;
for (let i = 0; i < arr.length; i ) {
if (typeof arr[i] === "number") sum = sum arr[i];
else if (Array.isArray(arr[i])) sum = sum arraySum(arr[i]);
}
return sum;
};
這是我失敗的單元測驗:
test("it should sum up from deeply nested arrays", () => {
type ValueOrArray = number | Array<ValueOrArray>;
const createDeeplyNestedArray = (depth: number): ValueOrArray => {
let retval: ValueOrArray = [1];
for (let i = 0; i < depth - 1; i ) {
retval = [1, retval];
}
return retval;
};
const NUMBER_OF_ELEMENTS = 100000;
const arr = createDeeplyNestedArray(NUMBER_OF_ELEMENTS);
expect(arraySum(arr)).toEqual(NUMBER_OF_ELEMENTS);
});
uj5u.com熱心網友回復:
函式記憶體存盤在稱為“呼叫堆疊”的東西上。每當你呼叫一個函式時,它的所有變數都會被分配并壓入“堆疊”,當函式回傳時,它們會從堆疊中彈出。給定以下代碼:
const a = () => {
}
const b = () => {
a()
// some code
}
const c = () => {
b()
}
c()
呼叫時c,您的呼叫堆疊將包含c. c呼叫時b,所有用于變數的記憶體b都被添加到堆疊中。當b呼叫時a,所有用于變數的記憶體a都被添加到堆疊中。當a完成執行時(所以當你到達“一些代碼”時),相關的變數a被釋放并從堆疊中洗掉。
您在這里遇到的問題是,每次您的函式遞回呼叫自身時,都會將更多記憶體分配到堆疊上。為了停止這種代碼耗盡所有系統記憶體,運行時限制了堆疊可以得到的大小——這就是你遇到這個錯誤的原因。
要通過此測驗,您需要一個不會在每次遇到陣列中的陣列時都呼叫自身的解決方案。這是我的解決方案,有效地使用陣列作為緩沖區;每次我點擊一個嵌套陣列時,我都會將它添加到緩沖區中。一旦我完成了外部陣列的處理,我就會檢查緩沖區中是否還有任何陣列。
export const arraySum = (arr) => {
let sum = 0;
const buffer = [arr];
while (buffer.length > 0) {
const next = buffer.shift();
for (let i = 0; i < next.length; i ) {
if (typeof next[i] === "number") sum = sum next[i];
else if (Array.isArray(next[i])) buffer.push(next[i]);
}
}
return sum;
};
uj5u.com熱心網友回復:
就像基思說的那樣,這不起作用,因為您正在達到最大呼叫堆疊大小。
RangeError: Maximum call stack size exceeded 是 JavaScript 中拋出的一種錯誤,當函式呼叫超出程式的堆疊大小時。呼叫堆疊是一種資料結構,用于跟蹤已呼叫的函式以及呼叫順序。
也許您可以嘗試以這樣的迭代方式解決它:
const arraySum = (arr) => {
if (!Array.isArray(arr)) return 0;
let sum = 0;
while (Array.isArray(arr)) {
let arrCopy = [];
for (let i = 0; i < arr.length; i ) {
if (typeof arr[i] === "number") sum = sum arr[i];
else if (Array.isArray(arr[i])) arrCopy = arrCopy.concat(arr[i]);
}
arr = arrCopy.length > 0 ? arrCopy : null;
}
return sum;
};
uj5u.com熱心網友回復:
我們可以使用堆疊或佇列來代替遞回。此外,順序并不重要。
function f(A) {
let sum = 0;
let stack = [A];
while (stack.length > 0) {
stack.pop().forEach(e => {
if (Array.isArray(e))
stack.push(e);
else if (typeof e === "number")
sum = e;
});
}
return sum;
}
console.log(f([1,2,[3,[4]]]));
uj5u.com熱心網友回復:
將flat避免嵌套深度接近10_000或更高的非常深嵌套陣列的呼叫堆疊錯誤的基于展平函式與reduce僅對數字型別求和的基于函式的方法確實解決了 OP 的問題。以下實作確實證明了這一點......
// Implementation
function flatAlmostInfiniteNestedArray(arr) {
while (arr.length < (arr = arr.flat(1000)).length) {
}
return arr;
}
function totalNestedNumberValues(arr) {
return flatAlmostInfiniteNestedArray(arr)
.reduce((total, value) => (
'number' === typeof value
? total value
: total
), 0);
}
// Test
const createDeeplyNestedArray = depth => {
let retval = [1];
for (let i = 0; i < depth - 1; i ) {
retval = [1, retval];
}
return retval;
};
const NUMBER_OF_ELEMENTS = 100000;
const arr = createDeeplyNestedArray(NUMBER_OF_ELEMENTS);
console.log(
'(totalNestedNumberValues(arr) === NUMBER_OF_ELEMENTS) ?..',
(totalNestedNumberValues(arr) === NUMBER_OF_ELEMENTS),
);
.as-console-wrapper { min-height: 100%!important; top: 0; }
轉載請註明出處,本文鏈接:https://www.uj5u.com/shujuku/492020.html
標籤:javascript 算法
