递归查找对象 属性 的路径
Find path of object property, recursively
我想动态打印对象键的路径。这是我的代码:
const Tree = ({ data }) => {
let path = "onboarding";
return Object.keys(data).map((key) => {
if (Array.isArray(data[key])) {
path = path + "." + key;
return (
<Tree data={data[key]}></Tree>
);
}
if (typeof data[key] === "object") {
path = path + "." + key;
return (
<Tree data={data[key]}></Tree>
);
} else {
path = path + "." + key;
return (
<input defaultValue={data[key]}
style={{ fontWeight: "bold" }}
disabled={!this.props.isEditable}/>
);
}
});
};
及其我的数据
onboarding: {
enumType: 1,
key: "key1",
steps: [
{
title: "STEP ONE",
description: "des1",
instructions: [
{
icon: "step_power",
label: {
text: "text1",
color: "A11111",
location: "top",
},
},
],
},
{
title: "STEP TWO",
description: "des2",
instructions: [
{
icon: "step_power",
label: {
text: "text2",
color: "A11111",
location: "top",
},
},
],
}
我想为每次迭代打印密钥路径,预期输出:
- “枚举类型”
- “钥匙”
- “步骤”
- “步数[0]”
- “步骤[0].title”
- 。 . .
- "步骤[1].说明[0].label.location"
你必须传递路径作为道具,我做了一个代码框:https://codesandbox.io/s/old-browser-crgd9r
编辑:根据评论建议在此处添加相关代码
const Tree = ({ path, data }) => {
// We have 3 cases: Array, Object or neither
// If we have an array we want to cycle through the elements
// and keep track of the index
// If we have an object we want to cicle through the keys
// otherwise just return the value
if (Array.isArray(data)) {
return data.map((element, index) => {
let currentPath = `${path}[${index}]`;
return (
<Tree
path={currentPath}
data={element}
key={currentPath}
></Tree>
);
});
} else if (data instanceof Object) {
return Object.keys(data).map((key) => {
let currentPath = path !== "" ? `${path}.${key}` : key;
return <Tree data={data[key]} path={currentPath} key={currentPath} />;
});
} else {
return (
<div>
<label>{path}</label>
<input defaultValue={data} style={{ fontWeight: "bold" }} />
</div>
);
}
};
另一种方法是将 path-extraction 代码与 DOM-generation 部分分开。这将使您能够使用更多可重用的函数。
下面是我可能会用两种不同的方式来写 path-extraction 的文章。首先作为输出格式的 all-in 一个函数:
const stringPaths = (o, p = '') =>
Array .isArray (o)
? o .flatMap ((v, i) => [p, ...stringPaths (v, `${p}[${i}]`)]) .filter (Boolean)
: Object (o) === o
? [
p,
... Object .entries (o) .flatMap (([k, v]) => stringPaths (v, p ? `${p}.${k}` : k))
] .filter (Boolean)
: p
const onboarding = {enumType: 1, key: "key1", steps: [{title: "STEP ONE", description: "des1", instructions: [{icon: "step_power", label: {text: "text1", color: "A11111", location: "top"}}]}, {title: "STEP TWO", description: "des2", instructions: [{icon: "step_power", label: {text: "text2", color: "A11111", location: "top"}}]}]}
console .log (stringPaths (onboarding))
.as-console-wrapper {max-height: 100% !important; top: 0}
其次,以我喜欢的方式,生成一种更广泛使用的中间格式([["enumType"], ["key"], ["steps"], ["steps", 0], ["steps", 0, "title"], ..., ["steps", 1, "instructions", 0, "label", "location"]]
,然后将其转换为您的目标格式:
const getPaths = (o) => Object (o) === o
? Object .entries (o)
.flatMap (([k, v], _, __, k1 = Array .isArray (o) ? Number (k) : k) =>
[[k1], ...getPaths (v) .map (p => [k1, ...p])]
)
: []
const stringPaths = (o) =>
getPaths (o) .map (
(path) => path .reduce ((p, n, i) => i == 0 ? n : Number .isInteger (n) ? `${p}[${n}]` : `${p}.${n}`, ``)
)
const onboarding = {enumType: 1, key: "key1", steps: [{title: "STEP ONE", description: "des1", instructions: [{icon: "step_power", label: {text: "text1", color: "A11111", location: "top"}}]}, {title: "STEP TWO", description: "des2", instructions: [{icon: "step_power", label: {text: "text2", color: "A11111", location: "top"}}]}]}
console .log (stringPaths (onboarding))
.as-console-wrapper {max-height: 100% !important; top: 0}
我认为这种细分有助于更好地编写代码。
我想动态打印对象键的路径。这是我的代码:
const Tree = ({ data }) => {
let path = "onboarding";
return Object.keys(data).map((key) => {
if (Array.isArray(data[key])) {
path = path + "." + key;
return (
<Tree data={data[key]}></Tree>
);
}
if (typeof data[key] === "object") {
path = path + "." + key;
return (
<Tree data={data[key]}></Tree>
);
} else {
path = path + "." + key;
return (
<input defaultValue={data[key]}
style={{ fontWeight: "bold" }}
disabled={!this.props.isEditable}/>
);
}
});
};
及其我的数据
onboarding: {
enumType: 1,
key: "key1",
steps: [
{
title: "STEP ONE",
description: "des1",
instructions: [
{
icon: "step_power",
label: {
text: "text1",
color: "A11111",
location: "top",
},
},
],
},
{
title: "STEP TWO",
description: "des2",
instructions: [
{
icon: "step_power",
label: {
text: "text2",
color: "A11111",
location: "top",
},
},
],
}
我想为每次迭代打印密钥路径,预期输出:
- “枚举类型”
- “钥匙”
- “步骤”
- “步数[0]”
- “步骤[0].title”
- 。 . .
- "步骤[1].说明[0].label.location"
你必须传递路径作为道具,我做了一个代码框:https://codesandbox.io/s/old-browser-crgd9r
编辑:根据评论建议在此处添加相关代码
const Tree = ({ path, data }) => {
// We have 3 cases: Array, Object or neither
// If we have an array we want to cycle through the elements
// and keep track of the index
// If we have an object we want to cicle through the keys
// otherwise just return the value
if (Array.isArray(data)) {
return data.map((element, index) => {
let currentPath = `${path}[${index}]`;
return (
<Tree
path={currentPath}
data={element}
key={currentPath}
></Tree>
);
});
} else if (data instanceof Object) {
return Object.keys(data).map((key) => {
let currentPath = path !== "" ? `${path}.${key}` : key;
return <Tree data={data[key]} path={currentPath} key={currentPath} />;
});
} else {
return (
<div>
<label>{path}</label>
<input defaultValue={data} style={{ fontWeight: "bold" }} />
</div>
);
}
};
另一种方法是将 path-extraction 代码与 DOM-generation 部分分开。这将使您能够使用更多可重用的函数。
下面是我可能会用两种不同的方式来写 path-extraction 的文章。首先作为输出格式的 all-in 一个函数:
const stringPaths = (o, p = '') =>
Array .isArray (o)
? o .flatMap ((v, i) => [p, ...stringPaths (v, `${p}[${i}]`)]) .filter (Boolean)
: Object (o) === o
? [
p,
... Object .entries (o) .flatMap (([k, v]) => stringPaths (v, p ? `${p}.${k}` : k))
] .filter (Boolean)
: p
const onboarding = {enumType: 1, key: "key1", steps: [{title: "STEP ONE", description: "des1", instructions: [{icon: "step_power", label: {text: "text1", color: "A11111", location: "top"}}]}, {title: "STEP TWO", description: "des2", instructions: [{icon: "step_power", label: {text: "text2", color: "A11111", location: "top"}}]}]}
console .log (stringPaths (onboarding))
.as-console-wrapper {max-height: 100% !important; top: 0}
其次,以我喜欢的方式,生成一种更广泛使用的中间格式([["enumType"], ["key"], ["steps"], ["steps", 0], ["steps", 0, "title"], ..., ["steps", 1, "instructions", 0, "label", "location"]]
,然后将其转换为您的目标格式:
const getPaths = (o) => Object (o) === o
? Object .entries (o)
.flatMap (([k, v], _, __, k1 = Array .isArray (o) ? Number (k) : k) =>
[[k1], ...getPaths (v) .map (p => [k1, ...p])]
)
: []
const stringPaths = (o) =>
getPaths (o) .map (
(path) => path .reduce ((p, n, i) => i == 0 ? n : Number .isInteger (n) ? `${p}[${n}]` : `${p}.${n}`, ``)
)
const onboarding = {enumType: 1, key: "key1", steps: [{title: "STEP ONE", description: "des1", instructions: [{icon: "step_power", label: {text: "text1", color: "A11111", location: "top"}}]}, {title: "STEP TWO", description: "des2", instructions: [{icon: "step_power", label: {text: "text2", color: "A11111", location: "top"}}]}]}
console .log (stringPaths (onboarding))
.as-console-wrapper {max-height: 100% !important; top: 0}
我认为这种细分有助于更好地编写代码。