根据动态属性从对象数组中创建对象



我有一个对象数组

"options": [
{
"width": 10,
"height": 20
},
{
"width": 20,
"height": 40
},
{
"width": 30,
"height": 60
}
]

我想转换成下面的

{ width: [10, 20, 30], height: [20, 40, 60] }

现在请记住键是动态的。在本例中是widthheight

我确实有解决办法。

const pluck = (arr: Record<string, any> | undefined, property: string) => {
return arr?.map((obj: any) => {
return obj[property];
});
};
const unique = (arr: any[] | undefined) =>
arr ? Object.keys(Object.assign({}, ...arr)) : null;
const keys = unique(myArray);
const options = keys
? Object.fromEntries(keys.map((key) => [key, pluck(myArray, key)]))
: null;

但是我能把它写短一点吗?

最简单的方法就是编写一个循环。我们先从JavaScript开始,然后再回到types:

const result = {};
for (const entry of myArray) {
for (const key in entry) { // or: of Object.keys(entry)
const values = result[key] = result[key] ?? [];
values.push(entry[key]);
}
}

生活的例子:

const myArray = [
{
"width": 10,
"height": 20
},
{
"width": 20,
"height": 40
},
{
"width": 30,
"height": 60
}
];
const result = {};
for (const entry of myArray) {
for (const key in entry) { // or: of Object.keys(entry)
const values = result[key] = result[key] ?? [];
values.push(entry[key]);
}
}
console.log(result);
.as-console-wrapper {
max-height: 100% !important;
}

对于for (const key in entry)for (const key of Object.keys(entry),前者也访问继承属性。您的示例没有任何继承属性,但是如果您有它们,您可以添加hasOwnProperty检查,或者如果您不介意临时数组,使用of Object.keys(entry)

好,那么:类型。我原以为这很难,但事实并非如此,这让我怀疑我错过了什么。:-)我们将为它使用一个函数,这样我们就可以使用类型参数:

function condense<ObjType extends object>(array: ObjType[]) {
const result: Record<string, any> = {};
for (const entry of array) {
for (const key in entry) { // or: of Object.keys(entry)
const values = result[key] = result[key] ?? [];
values.push(entry[key]);
}
}
return result as {[key in keyof ObjType]: ObjType[key][]};
}
const result = condense(myArray);
console.log(result);

操场上联系

由于结果是随时间累积的,所以我在condense函数中使用了相当松散的类型,但是输入和输出的类型是正确的。例如,上面的result的结果是{ width: number[]; height: number[]; },这就是我们想要的。如果我们加入第三个不同类型的属性(比如description)(比如string),它甚至可以工作,给我们{ width: number[]; height: number[]; description: string[]; }: Playground link


目前流行的是使用reduce,但在这里没有理由使用它,它只会增加复杂性。

我使用for循环,因为它比map或reduce响应更快。

const options = [
{ "width": 10, "height": 20 },
{ "width": 20, "height": 40 },
{ "width": 30, "height": 60 }
];
//That I want convert to the following
//{ width: [10, 20, 30], height: [20, 40, 60] }
let newobj = new Object();
for( let a of options ){
for( let b of Object.keys(a) ){
if( !newobj[b] ) newobj[b]=[]; newobj[b].push(a[b]);
}
}
console.log(newobj)

详情见Array.prototype.reduce()

const input = [
{ width: 100, height: 100 },
{ width: 200, height: 200 },
{ width: 300, height: 300 },
];
const group = (someArrayOfObjects) => {
return someArrayOfObjects.reduce((acc, current) => {
Object.entries(current).forEach(([key, value]) => {
if (!acc[key]) {
acc[key] = [];
}
acc[key].push(value);
});
return acc;
}, {});
};
console.log(group(input))

var height = [], width = [];
options.forEach((op) =>{
height.push(op.height)
width.push(op.width)
})
var returnValue = {width: width, height: height}

最新更新