[英]Create new array of objects by grouping array of objects based on property value of each object in javascript
[英]Grouping an array of objects and assign new combined value to each object
從對象數組中,我想為每個對象添加一個alumni
屬性。 該屬性的值是具有相同school
值的所有對象的名稱以“-”分隔的串聯。
現在棘手的部分是我需要盡可能提高性能,因為初始對象數組非常大。
我想出了一個使用 groupBy school 的解決方案,在每個組中映射不同的名稱並將它們連接成一個字符串,然后在每個對象上循環以添加新的屬性和值,最后在每個組上循環以將所有對象放在一個新數組(撤消組)。
我確信有一種更清潔的方法可以做到這一點。 任何建議都非常受歡迎。
下面是初始數組,以及將新屬性添加到數組中每個對象的預期結果。
var initialArr = [
{name:"A", school:"LFM"},
{name:"B", school:"LFM"},
{name:"C", school:"PBE"},
{name:"D", school:"LFM"},
{name:"E", school:"BPE"},
{name:"F", school:"LFM"}
];
var expectedResult = [
{name:"A", school:"LFM", alumni:"A-B-D-F"},
{name:"B", school:"LFM", alumni:"A-B-D-F"},
{name:"C", school:"PBE", alumni:"C-E"},
{name:"D", school:"LFM", alumni:"A-B-D-F"},
{name:"E", school:"BPE", alumni:"C-E"},
{name:"F", school:"LFM", alumni:"A-B-D-F"}
];
我想說最有效的方法是創建一個將學校映射到名稱數組的對象。 然后map
初始數組:
var initialArr= [ {name:"A", school:"LFM"}, {name:"B", school:"LFM"}, {name:"C", school:"PBE"}, {name:"D", school:"LFM"}, {name:"E", school:"BPE"}, {name:"F", school:"LFM"} ]; var schoolObj = initialArr.reduce((a, { name, school }) => { a[school] = (a[school] || []); a[school].push(name); return a; }, {}); var expectedResult = initialArr.map(e => { e.alumni = schoolObj[e.school].join("-"); return e; }); console.log(expectedResult);
這是 O(n) 時間復雜度,但也是 O(n) 空間復雜度(我認為 - 在這方面仍在學習)。 您可以制作一個具有恆定空間的效率更低的 O(n^2) 解決方案,但由於您提到輸入數組非常大,我認為時間將是您最大的限制。
請注意,您可能必須對校友數組執行排序,在這種情況下,如果您使用有效的排序,時間復雜度可能為 O(n log n)(我將算法的選擇留給您)。
根據您的喜好過濾和映射數據。
const initialArr= [ {name:"A", school:"LFM"}, {name:"B", school:"LFM"}, {name:"C", school:"PBE"}, {name:"D", school:"LFM"}, {name:"E", school:"BPE"}, {name:"F", school:"LFM"} ] console.log( initialArr.map(x => ({ name: x.name, school: x.school, alumni: `${x.name}-${initialArr.filter(y => x.school === y.school && y.name !== x.name).map(y => y.name).join("-")}` })) )
你描述它的方式是有效的。
這僅取決於您如何准確地執行 groupBy 和其他部分。 如果沒有循環中的循環(並且沒有),則復雜度為O(n)
(線性),這是你能得到的最好的。 可能有一些微優化的空間,但這通常不是很有效,並且在大多數項目中不值得花時間。
編輯:最快的方法是基本的方法。 這是某人完成的測試,for 比 forEach 和 map 快 20 倍。
var initialArr= [ {name:"A", school:"LFM"}, {name:"B", school:"LFM"}, {name:"C", school:"PBE"}, {name:"D", school:"LFM"}, {name:"E", school:"BPE"}, {name:"F", school:"LFM"} ]; var expectedArr = [...initialArr]; //if you want even more speed, remove [...], but it will alter initialArr var schoolObject = Object.fromEntries(expectedArr.map(e => [e.school, []])); expectedArr.forEach((e) => schoolObject[e.school].push(e.name)); var keys = Object.keys(schoolObject); for(let k = 0; k< keys.length;k++) schoolObject[keys[k]] = schoolObject[keys[k]].join("-"); for(let i=0;i<expectedArr.length;i++) expectedArr[i].alumni = schoolObject[expectedArr[i].school]; console.log(initialArr);
我能想到的最快方法:
names
添加到 schoolObject const initialArr= [ {name:"A", school:"LFM"}, {name:"B", school:"LFM"}, {name:"C", school:"PBE"}, {name:"D", school:"LFM"}, {name:"E", school:"BPE"}, {name:"F", school:"LFM"} ]; var schoolObject = Object.fromEntries(initialArr.map(e => [e.school, []])); initialArr.forEach((e) => schoolObject[e.school].push(e.name)) var expectedResult = initialArr.map(e => { return {...e,alumni: schoolObject[e.school].join("-")}; }); console.log(expectedResult);
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.