gpt4 book ai didi

How to merge properties within an array of objects based on specific property(如何基于特定属性合并对象数组中的属性)

转载 作者:bug小助手 更新时间:2023-10-24 22:34:55 29 4
gpt4 key购买 nike



I am trying to merge related objects in an array of objects based on similar properties in a specific object key "name".

我正在尝试根据特定对象键“name”中的相似属性合并对象数组中的相关对象。


I have tried the following code but did not work:

我尝试了以下代码,但不起作用:




const students = [];

const obj = [{
"name": "A. Nasila",
"adm": "",
"class": "4p",
"mat": "80",
"eng": "",
"kis": ""
},
{
"name": "A. Nasila",
"adm": "4886",
"class": "",
"mat": "",
"eng": "",
"kis": "39"
},
{
"name": "Mtu Bure",
"adm": "",
"class": "3L",
"mat": "",
"eng": "86",
"kis": ""
},
{
"name": "A. Nasila",
"adm": "",
"class": "",
"mat": "",
"eng": "75",
"kis": ""
},
{
"name": "Mtu Bure",
"adm": "9790",
"class": "",
"mat": "77",
"eng": "",
"kis": "76"
}
];

const groupedData = obj.reduce((acc, cur) => {
const name = cur.name;
if (!acc[name]) {
acc[name] = {};
}

for (const key in cur) {
acc[name][key] = cur[key];
}

return acc;
}, {});

const result = Object.values(groupedData);

const jsonObject = JSON.stringify(result);

const div = document.getElementById("students");

const span = document.createElement("span");
span.innerHTML = jsonObject;

div.appendChild(span);

<div id="students">
</div>




Help me get the desired output as shown below;

帮助我获得所需的输出,如下所示;


[
{
"name": "A. Nasila",
"adm": "4886",
"class": "4p",
"mat": "80",
"eng": "75",
"kis": "39"
},
{
"name": "Mtu Bure",
"adm": "9790",
"class": "3L",
"mat": "77",
"eng": "86",
"kis": "76"
}
]

更多回答

You are overwriting every key on each iteration even if it is an empty string, so it will simply keep the last object by name. You need to check if the value is empty before setting it. for (const key in cur) { if (acc[name][key] === undefined || acc[name][key] === "") acc[name][key] = cur[key]; }

您将覆盖每个迭代中的每个键,即使它是一个空字符串,因此它只会按名称保留最后一个对象。在设置之前,您需要检查该值是否为空。For(Cur中的常量键){if(acc[名称][键]=未定义||acc[名称][键]=“”)acc[名称][键]=cur[键];}

优秀答案推荐

you can also use ??= operator ( Nullish coalescing assignment )

您还可以使用??=运算符(Null合并赋值)




const obj = 
[ { name: 'A. Nasila', adm: '', class: '4p', mat: '80', eng: '', kis: '' }
, { name: 'A. Nasila', adm: '4886', class: '', mat: '', eng: '', kis: '39' }
, { name: 'Mtu Bure', adm: '', class: '3L', mat: '', eng: '86', kis: '' }
, { name: 'A. Nasila', adm: '', class: '', mat: '', eng: '75', kis: '' }
, { name: 'Mtu Bure', adm: '9790', class: '', mat: '77', eng: '', kis: '76' }
];

const res = Object.values(obj.reduce((r,o) =>
{
r[o.name] ??= {};
Object.keys(o).forEach(k => r[o.name][k] ||= o[k]);
return r;
}, {}));

console.log( res )

.as-console-wrapper {max-height: 100% !important;top: 0;}
.as-console-row::after {display: none !important;}





This should work

这应该行得通




const students = [];

const obj = [
{
"name": "A. Nasila",
"adm": "",
"class": "4p",
"mat": "80",
"eng": "",
"kis": ""
},
{
"name": "A. Nasila",
"adm": "4886",
"class": "",
"mat": "",
"eng": "",
"kis": "39"
},
{
"name": "Mtu Bure",
"adm": "",
"class": "3L",
"mat": "",
"eng": "86",
"kis": ""
},
{
"name": "A. Nasila",
"adm": "",
"class": "",
"mat": "",
"eng": "75",
"kis": ""
},
{
"name": "Mtu Bure",
"adm": "9790",
"class": "",
"mat": "77",
"eng": "",
"kis": "76"
}
];

const groupedData = obj.reduce((acc, cur) => {
const name = cur.name;
if (!acc[name]) {
acc[name] = {};
}

// Iterate through the keys of the current object and merge them
for (const key in cur) {
if (cur.hasOwnProperty(key)) {
acc[name][key] = cur[key] || acc[name][key];
}
}

return acc;
}, {});

const result = Object.values(groupedData);

const jsonObject = JSON.stringify(result);

const div = document.getElementById("students");

const span = document.createElement("span");
span.innerHTML = jsonObject;

div.appendChild(span);

<!DOCTYPE html>
<html>
<head>
<title>Students</title>
</head>
<body>
<div id="students">
</div>

</body>
</html>




A little explanation of what's going on

对正在发生的事情作一点解释


First off, I used the reduce method to iterate through the array of objects (obj) and group them by the name property into the groupedData object.

首先,我使用Reduced方法迭代对象数组(Obj),并按名称属性将它们分组到grouedData对象中。


If the name property is encountered for the first time, I then create a new object for it. If it has already been encountered, we merge the current object's properties into the existing object.

如果name属性是第一次遇到,我就为它创建一个新的对象。如果已经遇到过,我们就把当前对象的属性合并到现有对象中。


I then converted the groupedData object into an array of values using Object.values method.

然后,我使用Object.Values方法将grouedData对象转换为一个值数组。


EDIT: Made it work dynamically with all keys.

编辑:使其与所有关键点动态工作。



Avoid using spread, intermediate arrays, and getting full object data with Object.entries() for best performance.

为了获得最佳性能,请避免使用散布、中间数组,并使用对象条目()获取完整的对象数据。


It's also not clear what to do if 2 objects contain the same non-empty property, while I overwrite with the latest, Mister Jojo for example keeps the first one.

如果两个对象包含相同的非空属性,而我用最新的对象覆盖,例如,Mister Jojo保留第一个对象,那么应该怎么做也不清楚。




console.log(
obj.reduce((r, item, obj) => (
(obj = r.map.get(item.name)) ?
Object.keys(item).forEach(k => k !== 'name' && item[k] && (obj[k] = item[k])) :
r.map.set(item.name, r.arr[r.arr.length] = item) , r
), {arr: [], map: new Map}
).arr
);

<script>
const obj = [{
"name": "A. Nasila",
"adm": "",
"class": "4p",
"mat": "80",
"eng": "",
"kis": ""
},
{
"name": "A. Nasila",
"adm": "4886",
"class": "",
"mat": "",
"eng": "",
"kis": "39"
},
{
"name": "Mtu Bure",
"adm": "",
"class": "3L",
"mat": "",
"eng": "86",
"kis": ""
},
{
"name": "A. Nasila",
"adm": "",
"class": "",
"mat": "",
"eng": "75",
"kis": ""
},
{
"name": "Mtu Bure",
"adm": "9790",
"class": "",
"mat": "77",
"eng": "",
"kis": "76"
}
];
</script>




And a benchmark:

和一个基准:


enter image description here




<script benchmark data-count="1000000">

const obj = [{
"name": "A. Nasila",
"adm": "",
"class": "4p",
"mat": "80",
"eng": "",
"kis": ""
},
{
"name": "A. Nasila",
"adm": "4886",
"class": "",
"mat": "",
"eng": "",
"kis": "39"
},
{
"name": "Mtu Bure",
"adm": "",
"class": "3L",
"mat": "",
"eng": "86",
"kis": ""
},
{
"name": "A. Nasila",
"adm": "",
"class": "",
"mat": "",
"eng": "75",
"kis": ""
},
{
"name": "Mtu Bure",
"adm": "9790",
"class": "",
"mat": "77",
"eng": "",
"kis": "76"
}
];

// @benchmark Jojo

Object.values(obj.reduce((r,o) =>
{
r[o.name] ??= {};
Object.keys(o).forEach(k => r[o.name][k] ||= o[k]);
return r;
},{}));

// @benchmark Alexander

obj.reduce((r, item, obj) => {
(obj = r.map.get(item.name)) ?
Object.keys(item).forEach(k => k !== 'name' && item[k] && (obj[k] = item[k])) :
r.map.set(item.name, r.arr[r.arr.length] = item);
return r;
}, {arr: [], map: new Map}
).arr

</script>

<script src="https://cdn.jsdelivr.net/gh/silentmantra/benchmark/loader.js"></script>






Is there a way to iterate through the code you've written inside if & else. Because am supposing it will be tiresome to use it on an object with many keys.




  • If you can assume they'll always be the same, you can hardcode them in a list.

  • If you can assume they'll always be the same in the same array, but can't be hardcoded, use Object.keys() on the first object.


Then you can construct an object from an array of [key, value] tuples thanks to Object.fromEntries().

然后,您就可以使用由[key,Value]元组组成的数组来构造对象,这要归功于Object.FromEntry()。


You can't use the ?? operator for your values because you are using falsy values like empty strings.

你不能使用??运算符,因为您使用的是空字符串之类的假值。


const keys = Object.keys(obj[0])

const result = Object.values(
obj.reduce(
(acc, curr) => ({
...acc,
[curr.name]: Object.fromEntries(
keys.map((key) => [key, curr[key] || acc[curr.name]?.[key]])
),
}),
{}
)
)

PS: In terms of performance, some other answers are a lot better than this one. But unless this code will be executed in a hot path of your application, there is no need to optimize this, and make your code unreadable.

PS:就性能而言,其他一些答案比这个好得多。但是,除非该代码将在应用程序的热路径中执行,否则没有必要对此进行优化,从而使您的代码不可读。


更多回答

Thanks so much.

非常感谢。

@Drarig29 That's my answer, so I'll use my indentation style.

@drarig29这就是我的答案,所以我将使用我的缩进风格。

@MisterJojo Fine 😉

@MisterJojo Fine😉

That is great! Is there a way to iterate through the code you've written inside if & else. Because am supposing it will be tiresome to use it on an object with many keys.

太棒了!有没有一种方法可以迭代您在If&Else中编写的代码。因为我认为在一个有许多关键点的对象上使用它会很麻烦。

@AbednegoNasila I have updated my answer to match your requirement.

@AbednegoNasila我已经更新了我的答案以满足您的要求。

If the obj array is very long, you might want to omit name from keys.

如果obj数组很长,您可能希望从键中省略name。

Well, if the OP really needs something optimized because it's a hot path of their application, they should not use my answer at all.

好吧,如果OP确实需要优化一些东西,因为这是他们的应用程序的热门路径,他们根本不应该使用我的答案。

29 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com