簡體   English   中英

對對象數組進行分組並為每個對象分配新的組合值

[英]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);

我能想到的最快方法:

  1. 創建一個具有所有學校屬性的對象
  2. 將所有names添加到 schoolObject
  3. 將結果附加到連接值。

 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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM