如何从 javascript 中的嵌套对象数组递归创建平面数组?
How do I create a flat array from a nested array of objects in javascript recursively?
我要转换以下数据结构:
const data = [
{
regions: ['United States', 'Canada']
},
{
regions: ['United States']
},
{
prop1: {
regions: ['Canada']
}
},
{
prop2: [
{
regions: ['Mexico', 'United States'],
prop3: {
regions: ['Canada']
}
}
]
}
];
进入如下数据结构:
['United States', 'Canada', 'United States', 'Canada', 'Mexico', 'United States', 'Canada']
为了安全起见,我希望使用 .reduce
和 .map
递归地使用 ES6 执行此操作。
这是我迄今为止尝试过的方法,但它只深入了 2 个级别:
export const flattenArray = (arr: Object[], prop: string): any[] =>
arr.reduce(
(a, c) => [
...new Set([
...a,
...c.map(x => x[prop]).reduce((y, z) => [...y, ...z.map(j => j)], []),
]),
],
[]
);
更新:下面我没有使用@deterjan 和他的解决方案。如果有人需要非 .flat
版本,这是他在 .reduce
的单个函数中的解决方案
export const flatten = (obj: any, prop: string): any[] => [
...new Set(
Object.keys(obj).reduce((a, c) => {
if (c === prop) {
if (isArray(obj[prop])) {
return [...a, ...obj[c]];
} else {
return [...a, obj[c]];
}
} else if (isArray(obj[c])) {
return [
...a,
...obj[c].reduce((a, c) => [...a, ...flatten(c, prop)], []),
];
} else if (isObject(obj)) {
return [...a, ...flatten(obj[c], prop)];
} else {
return a;
}
}, [])
),
];
console.log(flatten(data, 'regions'));
不确定这是否是您要查找的内容,但以下代码递归地将对象和数组映射到它们的“区域”键,并在每一步展平。
function isArray(what) {
return Object.prototype.toString.call(what) === '[object Array]';
}
function searchObj(obj) {
return Object.keys(obj).map(key => {
if (key == "regions" && isArray(obj.regions)) return obj[key];
else if (isArray(obj[key])) return searchArray(obj[key]);
else if (typeof obj === "object") return searchObj(obj[key]);
else return [];
}).flat();
}
function searchArray(obj) {
return obj.map(elem => searchObj(elem)).flat();
}
用法:
searchObj(data)
> ["United States", "Canada", "United States", "Canada", "Mexico", "United States", "Canada"]
编辑:这是来自 https://unpkg.com/array-flat-polyfill@1.0.1/index.js
的 Array.flat() polyfill
Array.prototype.flat||Object.defineProperty(Array.prototype,"flat",{configurable:!0,value:function r(){var t=isNaN(arguments[0])?1:Number(arguments[0]);return t?Array.prototype.reduce.call(this,function(a,e){return Array.isArray(e)?a.push.apply(a,r.call(e,t-1)):a.push(e),a},[]):Array.prototype.slice.call(this)},writable:!0}),Array.prototype.flatMap||Object.defineProperty(Array.prototype,"flatMap",{configurable:!0,value:function(r){return Array.prototype.map.apply(this,arguments).flat()},writable:!0})
这是一个使用对象作为 json 的解决方案,然后使用正则表达式在其中搜索 expresion.I 猜测存在其他方式以更好的方式构建正则表达式,因为我不得不使用replace 方法删除 quotes.You 可以使用一些工具来衡量性能。
const data = {
sourceId: {
S: "some_string"
},
ignored: {
BOOL: false
},
stepFunctionArn: {
S: "some_string"
},
certificate: {
BOOL: true
},
infoNeeded: {
L: [
"Array"
]
},
queuesLinks: {
M: [
"Object"
]
},
};
[...JSON.stringify(data).matchAll(/(?:\"regions\"\:\[)(?:\")(.*?)(?:\")\]/gi)].reduce(function(a, v) {
a = a.concat(v[1].replace(/\"/g,"").split(','));
return a;
}, [])
我要转换以下数据结构:
const data = [
{
regions: ['United States', 'Canada']
},
{
regions: ['United States']
},
{
prop1: {
regions: ['Canada']
}
},
{
prop2: [
{
regions: ['Mexico', 'United States'],
prop3: {
regions: ['Canada']
}
}
]
}
];
进入如下数据结构:
['United States', 'Canada', 'United States', 'Canada', 'Mexico', 'United States', 'Canada']
为了安全起见,我希望使用 .reduce
和 .map
递归地使用 ES6 执行此操作。
这是我迄今为止尝试过的方法,但它只深入了 2 个级别:
export const flattenArray = (arr: Object[], prop: string): any[] =>
arr.reduce(
(a, c) => [
...new Set([
...a,
...c.map(x => x[prop]).reduce((y, z) => [...y, ...z.map(j => j)], []),
]),
],
[]
);
更新:下面我没有使用@deterjan 和他的解决方案。如果有人需要非 .flat
版本,这是他在 .reduce
export const flatten = (obj: any, prop: string): any[] => [
...new Set(
Object.keys(obj).reduce((a, c) => {
if (c === prop) {
if (isArray(obj[prop])) {
return [...a, ...obj[c]];
} else {
return [...a, obj[c]];
}
} else if (isArray(obj[c])) {
return [
...a,
...obj[c].reduce((a, c) => [...a, ...flatten(c, prop)], []),
];
} else if (isObject(obj)) {
return [...a, ...flatten(obj[c], prop)];
} else {
return a;
}
}, [])
),
];
console.log(flatten(data, 'regions'));
不确定这是否是您要查找的内容,但以下代码递归地将对象和数组映射到它们的“区域”键,并在每一步展平。
function isArray(what) {
return Object.prototype.toString.call(what) === '[object Array]';
}
function searchObj(obj) {
return Object.keys(obj).map(key => {
if (key == "regions" && isArray(obj.regions)) return obj[key];
else if (isArray(obj[key])) return searchArray(obj[key]);
else if (typeof obj === "object") return searchObj(obj[key]);
else return [];
}).flat();
}
function searchArray(obj) {
return obj.map(elem => searchObj(elem)).flat();
}
用法:
searchObj(data)
> ["United States", "Canada", "United States", "Canada", "Mexico", "United States", "Canada"]
编辑:这是来自 https://unpkg.com/array-flat-polyfill@1.0.1/index.js
的 Array.flat() polyfillArray.prototype.flat||Object.defineProperty(Array.prototype,"flat",{configurable:!0,value:function r(){var t=isNaN(arguments[0])?1:Number(arguments[0]);return t?Array.prototype.reduce.call(this,function(a,e){return Array.isArray(e)?a.push.apply(a,r.call(e,t-1)):a.push(e),a},[]):Array.prototype.slice.call(this)},writable:!0}),Array.prototype.flatMap||Object.defineProperty(Array.prototype,"flatMap",{configurable:!0,value:function(r){return Array.prototype.map.apply(this,arguments).flat()},writable:!0})
这是一个使用对象作为 json 的解决方案,然后使用正则表达式在其中搜索 expresion.I 猜测存在其他方式以更好的方式构建正则表达式,因为我不得不使用replace 方法删除 quotes.You 可以使用一些工具来衡量性能。
const data = {
sourceId: {
S: "some_string"
},
ignored: {
BOOL: false
},
stepFunctionArn: {
S: "some_string"
},
certificate: {
BOOL: true
},
infoNeeded: {
L: [
"Array"
]
},
queuesLinks: {
M: [
"Object"
]
},
};
[...JSON.stringify(data).matchAll(/(?:\"regions\"\:\[)(?:\")(.*?)(?:\")\]/gi)].reduce(function(a, v) {
a = a.concat(v[1].replace(/\"/g,"").split(','));
return a;
}, [])