我有這個 Javascript 物件:
{
title: "Securities Finance Trade Entry",
children: [
{
containerType: "Tabs",
children: [
{
title: "Common",
children: [
{
containerType: "Row",
children: [
{
input: "ComboBox",
label: "Trade Type",
options: ["Repo", "Buy/Sell", "FeeBased"],
value: "FeeBased"
},
{
input: "ComboBox",
label: "Direction",
options: ["Loan", "Borrow"],
value: "Borrow"
}
]
},
{
containerType: "Row",
children: [
{
containerType: "Column",
children: [
{
containerType: "Row",
children: [
{
input: "Text",
label: "Book",
value: "test"
},
{
input: "Text",
label: "Counterparty",
value: "test"
}
]
},
{
containerType: "Row",
children: [
{
input: "Date",
label: "StartDate",
value: "10/02/2021"
},
{
input: "Date",
label: "EndDate",
value: "10/02/2021"
}
]
},
{
containerType: "Row",
children: [
{
input: "Text",
label: "Security",
value: "test"
},
{
input: "Numeric",
label: "Quantity",
value: "test"
}
]
}
]
}
]
}
]
}
]
}
]
}
給定一個特定標簽,我需要找到具有該標簽的物件,然后替換該值,我遇到的問題是這種格式可能更加嵌套,我無法查看任何特定級別,我需要查看所有級別的所有物件然后只需替換標簽匹配的值。我嘗試了遞回,但無法使其正常作業,請有人建議嗎?
編輯:
這是我的嘗試,但失敗了:)
const deepReplace = (obj, id, value) => {
if (obj.children) {
obj = obj.children.map((childObj) => {
if (typeof childObj === "object") {
deepReplace(childObj, id, value)
}
})
return obj;
};
if (obj.label === id) {
obj['value'] = value;
return obj
};
};
const newObj = deepReplace(myObj, 'TradeType', 'Repo')
uj5u.com熱心網友回復:
這個問題似乎很適合遞回。由于我們必須多次重復操作,我們不確定有多少。
- 基本情況:如果標簽存在并且與要求的相同,則更改值
- 如果標簽不存在或不同,則檢查屬性children是否存在,然后對其進行迭代并重復 1 和 2。
// passed (obj, "Book", "changed")
const replaceValueOfTheLabel = (obj, label, value) => {
if (obj.label === label) {
return obj.value = value;
}
if (obj.children)
for (const ob of obj.children) {
replaceValueOfTheLabel(ob, label, value)
}
}
const obj = {
title: "Securities Finance Trade Entry",
children: [{
containerType: "Tabs",
children: [{
title: "Common",
children: [{
containerType: "Row",
children: [{
input: "ComboBox",
label: "Trade Type",
options: ["Repo", "Buy/Sell", "FeeBased"],
value: "FeeBased"
},
{
input: "ComboBox",
label: "Direction",
options: ["Loan", "Borrow"],
value: "Borrow"
}
]
},
{
containerType: "Row",
children: [{
containerType: "Column",
children: [{
containerType: "Row",
children: [{
input: "Text",
label: "Book",
value: "test"
},
{
input: "Text",
label: "Counterparty",
value: "test"
}
]
},
{
containerType: "Row",
children: [{
input: "Date",
label: "StartDate",
value: "10/02/2021"
},
{
input: "Date",
label: "EndDate",
value: "10/02/2021"
}
]
},
{
containerType: "Row",
children: [{
input: "Text",
label: "Security",
value: "test"
},
{
input: "Numeric",
label: "Quantity",
value: "test"
}
]
}
]
}]
}
]
}]
}]
}
replaceValueOfTheLabel(obj, "Book", "changed");
console.log(obj);
uj5u.com熱心網友回復:
如果您對不改變原始資料但回傳替換了適當值的副本的答案感興趣,它可能如下所示:
const deepReplace = (label, value) => (obj) => Object (obj) === obj
? { ... obj,
... (obj .label == label ? {value} : {}),
... (obj .children ? {children: obj .children .map (deepReplace (label, value))} : {})
}
: obj
const input = {title: "Securities Finance Trade Entry", children: [{containerType: "Tabs", children: [{title: "Common", children: [{containerType: "Row", children: [{input: "ComboBox", label: "Trade Type", options: ["Repo", "Buy/Sell", "FeeBased"], value: "FeeBased"}, {input: "ComboBox", label: "Direction", options: ["Loan", "Borrow"], value: "Borrow"}]}, {containerType: "Row", children: [{containerType: "Column", children: [{containerType: "Row", children: [{input: "Text", label: "Book", value: "test"}, {input: "Text", label: "Counterparty", value: "test"}]}, {containerType: "Row", children: [{input: "Date", label: "StartDate", value: "10/02/2021"}, {input: "Date", label: "EndDate", value: "10/02/2021"}]}, {containerType: "Row", children: [{input: "Text", label: "Security", value: "test"}, {input: "Numeric", label: "Quantity", value: "test"}]}]}]}]}]}]}
console .log (deepReplace ('Counterparty', '*** New value ***') (input))
.as-console-wrapper {max-height: 100% !important; top: 0}
我們測驗我們的輸入是否是一個物件。如果沒有,我們只需回傳它。如果是,我們通過包含物件的所有根屬性創建一個新物件,value如果我們有權限替換一個屬性label,然后在children節點上重復出現。
不可變資料有各種各樣的好處。我建議盡可能采用它。
更新:代碼說明
有評論表明這很難閱讀。這是我試圖解釋它的嘗試。
const deepReplace = (label, value) => (obj) => /* ... */
首先,我們對函式進行 curry,傳遞label并value取回另一個函式,該函式接受obj并回傳一個物件并進行更改。這在內部(我們稍后將傳遞對 的參考)和外部都很有用deepReplace (label, value),map因為我們現在可以只傳遞標簽和值并獲得可以應用于許多不同物件的函式。
然后我們開始一個條件運算子(三元)。我們測驗輸入引數是否為物件,使用Object (obj) === obj. 有很多方法可以對此進行測驗,包括typeof呼叫Object.prototype.toString()值。我覺得這個很健壯。
如果它不是一個物件,那么我們點擊最后一行: obj,并回傳原始值。如果它是一個物件,我們回傳一個由三個步驟創建的物件:
... obj,
Here we just spread the original object into our new one. This is a form of shallow cloning.
... (obj .label == label ? {value} : {}),
Here we test if the object's label property matches our target. If it does, we spread {value}, which is modern shorthand for {value: value} into our object. If it doesn't, we spread an empty object, thereby adding no properties.
... (obj .children ? {children: obj .children .map (deepReplace (label, value))} : {})
And here, we handle children. If our node has no children property, we spread an empty object. If it does, we map a recursive call to the same function over them, and spread in an object whose children property is the result. Here the currying helps, as we can just call map (deepReplace (label, value)) If our function looked like deepReplace = (label, value, obj) => /* ... */, then here we would have to call map ((item) => deepReplace (label, value, item)). It's not a big deal, but this way feels cleaner.
So in older JS, we might have written the equivalent code like this:
const deepReplace = (label, value) => (obj) => {
if (Object (obj) !== obj) {
return obj
}
const newObject = {...obj}
if (obj .label == label) {
newObject .value = value
}
if ('children' in obj) {
newObject .children = obj .children .map (deepReplace (label, value))
}
return newObject
}
That would have been essentially equivalent. I find the newer syntax more enlightening, but either would work.
We probably should have handled the array case, and that would add a little bit to the implementation, and an (untested) version might look like this:
const deepReplace = (label, value) => (obj) => Array .isArray (obj)
? obj .map (deepReplace (label, value))
: Object (obj) === obj
? { ... obj,
... (obj .label == label ? {value} : {}),
... (obj .children ? {children: obj .children .map (deepReplace (label, value))} : {})
}
: obj
Here we check for an array first, and if so, map the results, as we do for children.
轉載請註明出處,本文鏈接:https://www.uj5u.com/caozuo/434920.html
標籤:javascript 目的 递归 嵌套的
上一篇:為什么對于范圍為1到10**9的任何輸入值,此代碼都會出現無限回圈?
下一篇:存盤串列的所有r個組合
