要求:是否有任何最佳或簡單的方法來過濾掉陣列中的物件,該陣列包含基于其值的特定屬性而無需遞回。
問題陳述:我們可以使用遞回來實作此要求,但由于資料集(物件陣列)非常大并且每個物件包含n許多嵌套物件,遞回方法會導致性能問題。
這是示例模擬資料:
[{
children: [{
children: [{
children: [],
isWorking: 'yes'
}]
}]
}, {
children: [],
isWorking: 'no'
}, {
children: [{
children: [{
children: [],
isWorking: 'no'
}]
}]
}, {
children: [{
children: [],
isWorking: 'yes'
}]
}, ...]
isWorking我想從包含值為 as 的嵌套屬性的陣列中過濾出根物件yes。isWorking屬性將僅適用于不包含子物件的物件。IEchildren: []
正如我之前所說,我可以通過遞回來實作這一點,但我正在尋找不會影響性能的最佳解決方案。
這是我嘗試過的(作業解決方案):
const parent = [{
children: [{
children: [{
children: [],
isWorking: 'yes'
}]
}]
}, {
children: [],
isWorking: 'no'
}, {
children: [{
children: [{
children: [],
isWorking: 'no'
}]
}]
}, {
children: [{
children: [],
isWorking: 'yes'
}]
}];
const isWorkingFlagArr = [];
function checkForOccupation(arr) {
arr.forEach(obj => {
(!obj.children.length) ? isWorkingFlagArr.push(obj.isWorking === 'yes') : checkForOccupation(obj.children)
})
}
checkForOccupation(parent);
const res = parent.filter((obj, index) => isWorkingFlagArr[index]);
console.log(res);
uj5u.com熱心網友回復:
下面將每個遞回呼叫放在一個新的微任務上,從而避免炸毀堆疊。
此代碼運行與您的演算法相同的演算法,但確保在新的微任務上異步進行遞回呼叫。
在下面的代碼中??
一世。StackOverflow 不支持頂級異步。
二. 異步啟用等待的使用。
三. 異步 IIFE。
四. 你的演算法。
v. 暫停
for..of回圈的繼續,直到遞回呼叫回傳的承諾得到解決。類似于 a.then(() => checkForOccupation(children)),意味著遞回呼叫發生在微任務上的一個新堆疊上,從而緩解了深度嵌套遞回呼叫和 JS 中缺乏尾呼叫遞回優化的問題。這帶來了性能損失。六. 呼叫異步 IIFE 來啟動。
七. 呼叫外部異步 IIFE 以彌補 StackOverflow 缺乏頂級異步支持的不足。
(async () => { // i.
const getFlags = async (arr) => { // ii.
const flags = []
await (async function checkForOccupation(arr) { // iii.
for(const { children, isWorking } of arr) { // iv.
!children.length
? flags.push(isWorking === 'yes')
: await checkForOccupation(children) // v.
}
})(arr) // vi.
return flags
}
const data = [{
children: [{
children: [{
children: [],
isWorking: 'yes'
}]
}]
}, {
children: [],
isWorking: 'no'
}, {
children: [{
children: [{
children: [],
isWorking: 'no'
}]
}]
}, {
children: [{
children: [],
isWorking: 'yes'
}]
}]
const flags = await getFlags(data)
console.log(data.filter((_, index) => flags[index]))
})()
另一種方法是顯式管理狀態堆疊,這將是一件苦差事。
uj5u.com熱心網友回復:
我不知道這是否會比您的代碼執行得更好或更差,但我發現它簡單得多:
const checkForOccupation = (xs) => xs .flatMap (
(x, _, __, kids = checkForOccupation (x .children || [])) =>
x .isWorking == 'yes' || kids .length > 0 ? [{...x, children: kids}] : []
)
const data = [{children: [{children: [{children: [{children: [], isWorking: 'no'}], isWorking: 'yes'}]}]}, {children: [], isWorking: 'no'}, {children: [{children: [{children: [], isWorking: 'no'}]}]}, {children: [{children: [], isWorking: 'yes'}]}]
console .log (checkForOccupation (data))
.as-console-wrapper {max-height: 100% !important; top: 0}
我們使用flatMap一次轉換和過濾。我們首先在children我們節點的陣列上進行回圈(當該陣列為空時它會觸底)并檢查回傳的陣列是否有任何成員,或者我們的節點是否有魔法isWorking值。如果是這樣,我們回傳flatMap一個包含單個物件的陣列,該物件具有我們自己的屬性,并children替換為該遞回呼叫的結果。如果它沒有那個值或任何孩子,我們回傳flatMap一個空陣列。 flatMap然后展平回傳陣列的集合。
Ben Aston——在對問題的評論和他自己的回答中——擔心炸毀堆疊。據我所知,這只有在物件嵌套數千層時才會發生。如果您這樣做,我認為這可能是您遇到的最少的問題。
轉載請註明出處,本文鏈接:https://www.uj5u.com/shujuku/537115.html
上一篇:如何從字典生成配置組合?
