javascript - 制作嵌套在js中的平面对象
问题描述
我想将我的对象转换为嵌套对象,以便能够在反应中递归地渲染输入(如果输入在此输入下方有子输入渲染)有时输入的顺序错误,所以我必须像这样转换对象
const start = {
asdf: {
id: "asdf",
question: "How old are you?",
type: "text"
},
"asdf/zxcv": {
id: "asdf/zxcv",
expect: 18,
question: "Are you male?",
type: "text"
},
"asdf/zxcv/yuio": {
id: "asdf/zxcv/yuio",
expect: "yes",
question: "Do you like videogames?",
type: "text"
},
"asdf/dfgh": {
id: "asdf/dfgh",
expect: 21,
question: "Where do you live?",
type: "text"
},
"asdf/dfgh/fghj": {
id: "asdf/dfgh/fghj",
expect: "Boston",
question: "What's the weather?",
type: "text"
},
qwer: {
id: "qwer",
question: "What is your name?",
type: "text"
},
"qwer/asdf": {
id: "qwer/asdf",
expect: "David",
question: "What is your surname",
type: "text"
}
};
变成这样的东西
const result = {
asdf: {
id: "asdf",
question: "How old are you?",
type: "text",
subs: [
{
id: "asdf/zxcv",
expect: 18,
question: "Are you male?",
type: "text",
subs: [
{
id: "asdf/zxcv/yuio",
expect: "yes",
question: "Do you like videogames?",
type: "text"
}
]
},
{
id: "asdf/dfgh",
expect: 21,
question: "Where do you live?",
type: "text",
subs: [
{
id: "asdf/dfgh/fghj",
expect: "Boston",
question: "What's the weather?",
type: "text"
}
]
}
]
},
qwer: {
id: "qwer",
question: "What is your name?",
type: "text",
subs: [
{
id: "qwer/asdf",
expect: "David",
question: "What is your surname",
type: "text"
}
]
}
};
我可以创建第一级对象,但如果需要,我不知道如何将对象动态添加到 subs
这是我的尝试。它不起作用。
const createObjToRender = object => {
Object.values(object)
.filter(o => o)
.reduce((obj, el) => {
const idHistory = el.id.split("/");
if (idHistory.length > 1) {
let elToAddSubInput = obj;
for (let i = 0; i <= idHistory.length; i++) {
i === 0 && (elToAddSubInput = elToAddSubInput[idHistory[i]]);
i > 0 && (elToAddSubInput = elToAddSubInput.subs[idHistory[i]]);
}
elToAddSubInput.subs[idHistory.join("/")] = el;
}
if (idHistory.length === 1) {
const id = idHistory[0];
const { question, type } = el;
if (!obj[id]) {
obj[id] = {
id,
question,
type,
subs: {}
};
}
}
}, {});
};
解决方案
您可以使用嵌套哈希表来快速构建树:
const start = {
asdf: {
id: "asdf",
question: "How old are you?",
type: "text"
},
"asdf/zxcv": {
id: "asdf/zxcv",
expect: 18,
question: "Are you male?",
type: "text"
},
"asdf/zxcv/yuio": {
id: "asdf/zxcv/yuio",
expect: "yes",
question: "Do you like videogames?",
type: "text"
},
"asdf/dfgh": {
id: "asdf/dfgh",
expect: 21,
question: "Where do you live?",
type: "text"
},
"asdf/dfgh/fghj": {
id: "asdf/dfgh/fghj",
expect: "Boston",
question: "What's the weather?",
type: "text"
},
qwer: {
id: "qwer",
question: "What is your name?",
type: "text"
},
"qwer/asdf": {
id: "qwer/asdf",
expect: "David",
question: "What is your surname",
type: "text"
}
};
// We use a symbol to allow fast lookups while still having a resulting array without it
const lookup = Symbol();
const root = { [lookup]: {}, sub: [] };
// As the ids are part of the values itself, we can ignore the objects keys and directly iterate the values
for(const el of Object.values(start)) {
// Now we traverse down the nested lookup tree
let parent = root;
for(const part of el.id.split("/")) {
// If a certain path doesnt exist yet, set it up
if(!parent[lookup][part])
parent.sub.push(parent[lookup][part] = { [lookup]: {}, sub: [] });
// Dive deeper
parent = parent[lookup][part];
}
// We reached the node were the data belongs, so just assign it here:
Object.assign(parent, el);
}
// you could also get it as an array with root.sub
console.log(root[lookup]);
推荐阅读
- flutter - 如何实现条带作为 Flutter Web 的支付网关?
- r - 具有性别的人口金字塔并与 ggplot2 比较两个时间段
- c# - 如何解决 502 Bad Gateway 错误
- ios - Flurry iOS 测试推送通知因 UnrecognizedDeviceId 而失败
- docker - Confluent 的 Docker 映像 - 添加 Confluent Hub 连接器
- python-3.x - 从 django 查询集中的日期时间字典中提取日期
- docusignapi - 删除 DocuSign Payment 的 Send without Payment 能力
- python - 不和谐 | 嵌入间距
- function - Haskell 给出“变量不在范围内:[Integer] -> t
- react-native - 如何反应原生 Flatlist 动态高度网格?