我有這樣的輸入資料:
[
{
"name": "outField2",
"value": "something"
},
{
"name": "outField3[index].outField4",
"value": "something"
},
{
"name": "outField3[index].outField5",
"value": "something"
},
{
"name": "outField3[index].outField6.outField7",
"value": "something"
}
]
我正在嘗試基于子字串“[index]”來實作這樣的輸出(即,如果該子字串不存在,那么該元素應該是一個物件而不是陣列):
{
"outField2": "something",
"outField3[index]": [{
"outField4": "something",
"outField5": "something",
"outField6": {
"outField7": "something"
}
}]
}
如果沒有子字串'[index]',我當前的代碼(如下)能夠將 outField3 作為物件生成,但我無法找到一個好的解決方案來在存在子字串的情況下將其生成為陣列。有人可以幫忙嗎?我嘗試了一些選項,但都沒有給我想要的結果。
const map = [
{
"name": "outField2",
"value": "something"
},
{
"name": "outField3[index].outField4",
"value": "something"
},
{
"name": "outField3[index].outField5",
"value": "something"
},
{
"name": "outField3[index].outField6.outField7",
"value": "something"
}
];
let mapOutput = {};
map.forEach(doThis);
function doThis(item, index) {
let path = map[index].name.split(".");
if (path.length > 1) {
createNestedObject(mapOutput, path, map[index].value);
} else {
mapOutput[map[index].name] = map[index].value;
};
};
function createNestedObject(element, path, value) {
var lastElement = arguments.length === 3 ? path.pop() : false;
for (var i = 0; i < path.length; i ) {
if (path[i].includes('[index]')) {
/*some logic here to push the child elements
that do not contain [index] as an array into
the ones that contain [index]*/
} else {
element = element[path[i]] = element[path[i]] || {};
};
}
if (lastElement) element = element[lastElement] = value;
return element;
};
let mapOutputJSON = JSON.stringify(mapOutput, null, 2);
console.log(mapOutputJSON);
uj5u.com熱心網友回復:
你可以做這樣的事情
const data = [{
"name": "outField2",
"value": "something"
},
{
"name": "outField3[index].outField4",
"value": "something"
},
{
"name": "outField3[index].outField5",
"value": "something"
},
{
"name": "outField3[index].outField6.outField7",
"value": "something"
}
]
const buildObject = (paths, value, obj) => {
if (paths.length === 0) {
return value
}
const [path, ...rest] = paths
if(path.includes('[index]')) {
return {
...obj,
[path]: [buildObject(rest, value, (obj[path] || [])[0] || {})]
}
}
return {
...obj,
[path]: buildObject(rest, value, obj[path] || {})
}
}
const result = data.reduce((res, {
name,
value
}) => buildObject(name.split('.'), value, res), {})
console.log(result)
uj5u.com熱心網友回復:
在我看來,一種可能的通用方法也分配了 OP"outField3[index]"
屬性的正確型別(object
型別而不是Array
實體)是基于reduce
where ...
- 外回圈迭代
{ name, value }
專案陣列 - 通過執行單個函式
accumulateObjectTypeFromPathAndValue
...- 此函式將
split
每個name
值放入物件鍵陣列中path
,然后由內部方法迭代,reduce
其中傳遞的物件以編程方式累積嵌套的鍵值對。
- 此函式將
function accumulateObjectTypeFromPathAndValue(root, path, value) {
path
.split('.')
.reduce((obj, key, idx, arr) => {
if (!obj.hasOwnProperty(key)) {
Object.assign(obj, {
[ key ]: (idx === arr.length - 1)
? value
: {},
});
}
return obj[key];
}, root);
return root;
}
console.log(
[{
"name": "outField2",
"value": "something"
}, {
"name": "outField3[index].outField4",
"value": "something"
}, {
"name": "outField3[index].outField5",
"value": "something"
}, {
"name": "outField3[index].outField6.outField7",
"value": "something"
}].reduce((result, { name: path, value }) => {
return accumulateObjectTypeFromPathAndValue(result, path, value);
}, {})
);
.as-console-wrapper { min-height: 100%!important; top: 0; }
然后可以根據 OP 的自定義陣列型別要求更改上述第二個 reducer 函式的實作......
function accumulateCustomObjectTypeFromPathAndValue(root, path, value) {
path
.split('.')
.reduce((obj, key, idx, arr) => {
if (!obj.hasOwnProperty(key)) {
Object.assign(obj, {
[ key ]: (idx === arr.length - 1)
? value
: {},
});
if (key.endsWith('[index]')) {
obj[ key ] = [obj[ key ]];
}
}
return Array.isArray(obj[ key ])
//? obj[ key ].at(-1) // last item.
? obj[ key ][obj[ key ].length - 1] // last item.
: obj[ key ];
}, root);
return root;
}
console.log(
[{
"name": "outField2",
"value": "something"
}, {
"name": "outField3[index].outField4",
"value": "something"
}, {
"name": "outField3[index].outField5",
"value": "something"
}, {
"name": "outField3[index].outField6.outField7",
"value": "something"
}].reduce((result, { name: path, value }) => {
return accumulateCustomObjectTypeFromPathAndValue(result, path, value);
}, {})
);
.as-console-wrapper { min-height: 100%!important; top: 0; }
uj5u.com熱心網友回復:
在這個要求上花了一些時間之后,我想出了這個解決方案(我們可以使它更優化),但首先你能不能試試它,看看幾個例子,檢查它是否按照你的要求正常作業。
演示:
const inputArr = [
{
"name": "outField2",
"value": "something"
},
{
"name": "outField3[index].outField4",
"value": "something"
},
{
"name": "outField3[index].outField5",
"value": "something"
},
{
"name": "outField3[index].outField6.outField7",
"value": "something"
}
];
const searchSubStr = '[index]';
const obj = {};
let innerObj = {};
inputArr.forEach(({name, value}) => {
if (name.includes(searchSubStr)) {
const splittedStr = name.split(searchSubStr '.');
if (splittedStr[1].includes('.')) {
const split = splittedStr[1].split('.');
Object.assign(innerObj, { [split[0]]: {
[split[1]]: value
}})
} else {
Object.assign(innerObj, { [splittedStr[1]]: value })
}
obj[splittedStr[0] searchSubStr] = [innerObj]
} else {
if (name.includes('.')) {
const split = name.split('.');
Object.assign(obj, { [split[0]]: {
[split[1]]: value
}})
} else {
obj[name] = value
}
}
});
console.log(obj);
轉載請註明出處,本文鏈接:https://www.uj5u.com/ruanti/525602.html