如何从点符号字符串动态创建多级对象
How to dynamically create a multilevel object from a dot notation string
我有一些数据需要格式化。输入类似于
const data = [
['0','some name','ok'],
['0.1','some name','ok'],
['0.1.01','some name', 'ok'],
['0.1.01.01','some name','ok'],
['0.1.01.02','some name','ok'],
['1','some name','ok'],
]
我需要它像:
const data = [{
code: "0"
name: "some name"
status: "ok"
data:[{
code: "0.1"
name: "some name"
status: "ok"
data:[
{
code: "0.1.01"
name: "some name"
status: "ok"
data: []
},
{
code: "0.1.02"
name: "some name"
status: "ok"
data:[]
}
]
},
{
code: "1"
name: "some name"
status: "ok"
data[]
}
]
}]
我将使用此数据来填充可扩展的反应 table,我需要那种结构,因此 useExpanded 可以像这样处理可扩展的行
code | decription | status
__________________________________
- 0 | some text | ok
- 0.1 | some text | ok
+ 0.1.01 | some text | ok
+ 0.1.02 | some text | ok
+ 1 | some text | ok
所以'code'代表关卡,每个关卡都是一个对象数组
这是我到目前为止尝试过的方法。
const formatData = () => {
const data = [
['0','some name','ok'],
['0.1','some name','ok'],
['0.1.01','some name', 'ok'],
['0.1.01.01','some name','ok'],
['0.1.01.02','some name','ok'],
]
const columnName = ['code','name','status']
const result = [];
data.forEach((item) => {
let rowInfo = {};
item.forEach((item, index) => {
rowInfo = { ...rowInfo, [columnName[index]]: item };
});
if (item[0].split(".").length === 1) { // If is the first level
result.push({ ...rowInfo, subRows: [] });
} else {
let aux = item[0].split(".");
aux.slice(0, -1).reduce((r, e) => { // find parent and push object to array
r[e].subRows.push({ ...rowInfo, subRows: [] });
}, result);
}
});
return result;
}
我可以得到前 3 行,但程序在尝试查找子级数组时中断
首先:运行 您在调试器中的代码,看看它在做什么。不是你想的那样。
也许阅读 reduce() 的作用。
其次,重写它,这样您就不会在树中搜索插入行的位置。树的所有节点都有 ID,因此只需制作从这些 ID 到节点的映射。当你想找到一个节点时,只需在地图中查找它即可。
终于解决了
这是解决方案:
var array = ["1","1.1","1.1.01","1.1.02.1",'1.2.01' ];
result = array.reduce((r, s,rowNum) => {
const size = s.split(".").length-1
s.split('.').reduce((a, path,index) =>
let object = a.find(o => o.path === path);
if (!object && index===size) { // If object is not created and is the last child
//create object
a.push(object = { path, populate: [] });
} else {
// If object is not created but isn't the last
if(!object) throw `Error: ${rowNum}`; // parent object has not been created, notify user
}
return object.populate; // If there is an object and is not the last child, return it's own array of objects (child list)
}, r);
return r;
}, []);
console.log(result);
我使用第一个 reduce 从数组中获取每个项目并将其累积到一个数组中,然后我得到字符串将生成的“级别”数。
第二个 reduce 函数迭代将要创建的关卡。
如果是最后一级(或者如果它只有一级),那么我创建对象和 return 将包含子级对象的子数组,因此下一次迭代中的累加器是现在是子级别数组的引用。然后我检查是否是最后一级,如果不是,则 return 子级数组,如果对象不存在,则错误
我有一些数据需要格式化。输入类似于
const data = [
['0','some name','ok'],
['0.1','some name','ok'],
['0.1.01','some name', 'ok'],
['0.1.01.01','some name','ok'],
['0.1.01.02','some name','ok'],
['1','some name','ok'],
]
我需要它像:
const data = [{
code: "0"
name: "some name"
status: "ok"
data:[{
code: "0.1"
name: "some name"
status: "ok"
data:[
{
code: "0.1.01"
name: "some name"
status: "ok"
data: []
},
{
code: "0.1.02"
name: "some name"
status: "ok"
data:[]
}
]
},
{
code: "1"
name: "some name"
status: "ok"
data[]
}
]
}]
我将使用此数据来填充可扩展的反应 table,我需要那种结构,因此 useExpanded 可以像这样处理可扩展的行
code | decription | status
__________________________________
- 0 | some text | ok
- 0.1 | some text | ok
+ 0.1.01 | some text | ok
+ 0.1.02 | some text | ok
+ 1 | some text | ok
所以'code'代表关卡,每个关卡都是一个对象数组
这是我到目前为止尝试过的方法。
const formatData = () => {
const data = [
['0','some name','ok'],
['0.1','some name','ok'],
['0.1.01','some name', 'ok'],
['0.1.01.01','some name','ok'],
['0.1.01.02','some name','ok'],
]
const columnName = ['code','name','status']
const result = [];
data.forEach((item) => {
let rowInfo = {};
item.forEach((item, index) => {
rowInfo = { ...rowInfo, [columnName[index]]: item };
});
if (item[0].split(".").length === 1) { // If is the first level
result.push({ ...rowInfo, subRows: [] });
} else {
let aux = item[0].split(".");
aux.slice(0, -1).reduce((r, e) => { // find parent and push object to array
r[e].subRows.push({ ...rowInfo, subRows: [] });
}, result);
}
});
return result;
}
我可以得到前 3 行,但程序在尝试查找子级数组时中断
首先:运行 您在调试器中的代码,看看它在做什么。不是你想的那样。
也许阅读 reduce() 的作用。
其次,重写它,这样您就不会在树中搜索插入行的位置。树的所有节点都有 ID,因此只需制作从这些 ID 到节点的映射。当你想找到一个节点时,只需在地图中查找它即可。
终于解决了
这是解决方案:
var array = ["1","1.1","1.1.01","1.1.02.1",'1.2.01' ];
result = array.reduce((r, s,rowNum) => {
const size = s.split(".").length-1
s.split('.').reduce((a, path,index) =>
let object = a.find(o => o.path === path);
if (!object && index===size) { // If object is not created and is the last child
//create object
a.push(object = { path, populate: [] });
} else {
// If object is not created but isn't the last
if(!object) throw `Error: ${rowNum}`; // parent object has not been created, notify user
}
return object.populate; // If there is an object and is not the last child, return it's own array of objects (child list)
}, r);
return r;
}, []);
console.log(result);
我使用第一个 reduce 从数组中获取每个项目并将其累积到一个数组中,然后我得到字符串将生成的“级别”数。
第二个 reduce 函数迭代将要创建的关卡。
如果是最后一级(或者如果它只有一级),那么我创建对象和 return 将包含子级对象的子数组,因此下一次迭代中的累加器是现在是子级别数组的引用。然后我检查是否是最后一级,如果不是,则 return 子级数组,如果对象不存在,则错误