展平对象和限制嵌套数量 [英] Flattening object and limitting number of nesting
问题描述
我想限制对象内扁平结构的数量.考虑下面的例子.
输入:
const exampleObj = {富:{酒吧: {商务:你好"}}};
输出:
{foo_bar_biz: 你好"}
我想设置一个限制器(limit = 2),这样函数将停止执行递归函数并返回类似这样的东西
{foo_bar: [Object] 对象"}
这是一个片段:
const { useState, useEffect} = React;const exampleObj = {富:{酒吧: {商务:你好"}}};让限制= 0;功能应用(){const [state, setState] = useState({});useEffect(() => {展平(exampleObj);}, []);const flatten = (data, parent, result = {}) =>{for(让输入数据){const propName = 父级?parent + "_" + key : key;if (typeof data[key] === "object") {限制++;如果(限制 <= 1){展平(数据[键],道具名称,结果);} 别的 {setState(prevState => {返回 {...prevState,[道具名称]:typeof data[key] === "object" ?[对象] 对象":数据[键]};});}} 别的 {结果[propName] = 数据[key];设置状态({...状态,[道具名称]:数据[键]});}}};控制台日志(状态);返回 (<div><p>开始编辑以看到一些神奇的事情发生:)</p>
);}ReactDOM.render(
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.8.4/umd/react.production.min.js"></script><script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.8.4/umd/react-dom.production.min.js"></script><div id="root"></div>
我已经为此准备了一个解决方案,但它非常麻烦.https://stackblitz.com/edit/react-u5klvc
这是 flatten
的一种可能实现.注意它是如何与 React 或特定的 React 组件完全分离的.它适用于任何 JavaScript 对象 -
const snakecase = s =>s.join(_")const flatten = (t = {}, n = Infinity, join = snakecase) =>{ const many = (t, n, path) =>n >= 0 &&对象(t) === t?Object.entries(t).flatMap(_ => one(_, n - 1, path)): [ [ 加入(路径), t ] ]const one = ([ k, v ], n, path) =>许多(v,n,[...路径,k])返回 Object.fromEntries(many(t, n, []))}
举一些例子data
-
const data ={ a1: 11, a2: { b1: 21, b2: 22 }, a3: { b1: { c1: 311, c2: 312 }, b2: { c1: 321, c2: 322, c3: { d1: 3231 } }}}
1 的 depth
压平一层 -
flatten(data, 1)
{a1":11,a2_b1":21,a2_b2":22,a3_b1":{c1":311,c2":312},a3_b2":{c1":321,c2":322,c3":{d1":3231}}}
2 的 depth
压平了两个级别 -
flatten(data, 2)//=>...
{a1":11,a2_b1":21,a2_b2":22,a3_b1_c1":311,a3_b1_c2":312,a3_b2_c1":321,a3_b2_c2":322,a3_b2_c3":{d1":3231}}
默认depth
是无穷大-
flatten(data)//=>...
{a1":11,a2_b1":21,a2_b2":22,a3_b1_c1":311,a3_b1_c2":312,a3_b2_c1":321,a3_b2_c2":322,a3_b2_c3_d1":3231}
默认的join
是snakecase,但是可以在调用点指定参数-
const camelCase = ([ first = "", ...rest ]) =>first + rest.map(upperFirst).join("")const upperFirst = ([ first = "", ...rest ]) =>first.toUpperCase() + rest.join("")扁平化(数据,2,驼峰式)//=>...
{a1":11,a2B1":21,a2B2":22,a3B1C1":311,a3B1C2":312,a3B2C1":321,a3B2C2":322,a3B2C3":{d1":3231}}
展开下面的代码片段以在您自己的浏览器中验证结果 -
const data ={ a1: 11, a2: { b1: 21, b2: 22 }, a3: { b1: { c1: 311, c2: 312 }, b2: { c1: 321, c2: 322, c3: { d1: 3231 } }}}const snakecase = s =>s.join("_")const flatten = (t = {}, n = Infinity, join = snakecase) =>{ const many = (t, n, path) =>n >= 0 &&对象(t) === t?Object.entries(t).flatMap(_ => one(_, n - 1, path)): [ [ 加入(路径), t ] ]const one = ([ k, v ], n, path) =>许多(v,n,[...路径,k])返回 Object.fromEntries(many(t, n, []))}常量结果 =展平(数据,2)console.log(JSON.stringify(result, null, 2))
I would like to limit number of flattened structures inside an object. Consider example below.
Input:
const exampleObj = {
foo: {
bar: {
biz: "hello"
}
}
};
Output:
{foo_bar_biz: "hello"}
I wanted to set a limiter (limit = 2) so that function will stop performing recursive function and return something like this
{foo_bar: "[Object] object"}
Here's a snippet:
const { useState, useEffect} = React;
const exampleObj = {
foo: {
bar: {
biz: "hello"
}
}
};
let limit = 0;
function App() {
const [state, setState] = useState({});
useEffect(() => {
flatten(exampleObj);
}, []);
const flatten = (data, parent, result = {}) => {
for (let key in data) {
const propName = parent ? parent + "_" + key : key;
if (typeof data[key] === "object") {
limit++;
if (limit <= 1) {
flatten(data[key], propName, result);
} else {
setState(prevState => {
return {
...prevState,
[propName]:
typeof data[key] === "object" ? "[Object] object" : data[key]
};
});
}
} else {
result[propName] = data[key];
setState({
...state,
[propName]: data[key]
});
}
}
};
console.log(state);
return (
<div>
<p>Start editing to see some magic happen :)</p>
</div>
);
}
ReactDOM.render(<App />, document.getElementById("root"));
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.8.4/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.8.4/umd/react-dom.production.min.js"></script>
<div id="root"></div>
I've prepared a solution for that, but it is quite cumbersome. https://stackblitz.com/edit/react-u5klvc
Here's one possible implementation of flatten
. Notice how it's completely decoupled from React or a specific React component. It works on any JavaScript objects -
const snakecase = s =>
s.join("_")
const flatten = (t = {}, n = Infinity, join = snakecase) =>
{ const many = (t, n, path) =>
n >= 0 && Object(t) === t
? Object.entries(t).flatMap(_ => one(_, n - 1, path))
: [ [ join(path), t ] ]
const one = ([ k, v ], n, path) =>
many(v, n, [...path, k])
return Object.fromEntries(many(t, n, []))
}
Given some example data
-
const data =
{ a1: 11
, a2: { b1: 21, b2: 22 }
, a3: { b1: { c1: 311, c2: 312 }
, b2: { c1: 321, c2: 322, c3: { d1: 3231 } }
}
}
A depth
of 1 flattens one level -
flatten(data, 1)
{
"a1": 11,
"a2_b1": 21,
"a2_b2": 22,
"a3_b1": {
"c1": 311,
"c2": 312
},
"a3_b2": {
"c1": 321,
"c2": 322,
"c3": {
"d1": 3231
}
}
}
A depth
of 2 flattens two levels -
flatten(data, 2) // => ...
{
"a1": 11,
"a2_b1": 21,
"a2_b2": 22,
"a3_b1_c1": 311,
"a3_b1_c2": 312,
"a3_b2_c1": 321,
"a3_b2_c2": 322,
"a3_b2_c3": {
"d1": 3231
}
}
The default depth
is inifinity -
flatten(data) // => ...
{
"a1": 11,
"a2_b1": 21,
"a2_b2": 22,
"a3_b1_c1": 311,
"a3_b1_c2": 312,
"a3_b2_c1": 321,
"a3_b2_c2": 322,
"a3_b2_c3_d1": 3231
}
The default join
is snakecase, but the parameter can be specified at the call site -
const camelCase = ([ first = "", ...rest ]) =>
first + rest.map(upperFirst).join("")
const upperFirst = ([ first = "", ...rest ]) =>
first.toUpperCase() + rest.join("")
flatten(data, 2, camelCase) // => ...
{
"a1": 11,
"a2B1": 21,
"a2B2": 22,
"a3B1C1": 311,
"a3B1C2": 312,
"a3B2C1": 321,
"a3B2C2": 322,
"a3B2C3": {
"d1": 3231
}
}
Expand the snippet below to verify the results in your own browser -
const data =
{ a1: 11
, a2: { b1: 21, b2: 22 }
, a3: { b1: { c1: 311, c2: 312 }
, b2: { c1: 321, c2: 322, c3: { d1: 3231 } }
}
}
const snakecase = s =>
s.join("_")
const flatten = (t = {}, n = Infinity, join = snakecase) =>
{ const many = (t, n, path) =>
n >= 0 && Object(t) === t
? Object.entries(t).flatMap(_ => one(_, n - 1, path))
: [ [ join(path), t ] ]
const one = ([ k, v ], n, path) =>
many(v, n, [...path, k])
return Object.fromEntries(many(t, n, []))
}
const result =
flatten(data, 2)
console.log(JSON.stringify(result, null, 2))
这篇关于展平对象和限制嵌套数量的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!