簡體   English   中英

將兩個多維數組映射為一個對象

[英]Map Two Multi-dimensional Arrays into an Object

我在一次采訪中被要求將兩個多維數組處理成一個對象,其格式類似於:

{
   'sally': {
       id: 1,
       metrics: {
           sales: 6000,
           missed: 0
       }
   },
   'bob': {
       id: 2,
       metrics: {
           sales: 1000,
           missed: 0
       }
   },..
}

但是,我無法弄清楚。 我試過做嵌套的for循環,但問題是我擔心執行時間。 根據面試官的說法,它的執行時間應該是O(n) ,如果我正確理解 Big O,嵌套的 for 循環的執行時間應該是O(n^2)左右。 這是我到目前為止的代碼:

// returns a dictionary
let testIAteShitOn = (requested_user = false, requested_metric = false) => {
  // is the array always organized the same?
  let users = [
    [1, "Sally"],
    [2, "Bob"],
    [3, "George"],
  ];

  // same here, is this always organized the same?
  //  are there only ever 2 metrics?
  let metrics = [
    [1, "sales", 5000],
    [1, "sales", 1000],
    [3, "missed", 1000],
    [2, "sales", 1000],
  ];

 for (let i = users.length - 1; i >= 0; i--) {
    let id = users[i][0];
    let data = findDiamond(id, metrics);

 }

 return obj;

}


let findDiamond = (id, array) => {
    return array.filter((item) => item[0] == id);
}

我將不勝感激這方面的任何幫助以及關於在哪里以及如何最好地學習算法、數據結構和 Big O 的建議。

您可以使用兩個單獨的循環來獲得想要的結果,並使用一個幫助器對象,該對象通過id引用每個用戶。

 const users = [[1, "Sally"], [2, "Bob"], [3, "George"]], metrics = [[1, "sales", 5000], [1, "sales", 1000], [3, "missed", 1000], [2, "sales", 1000]], references = {}, result = {}; for (const [id, name] of users) { references[id] = result[name] = { id, metrics: { sales: 0, missed: 0} }; } for (const [id, metric, value] of metrics) { references[id].metrics[metric] += value; } console.log(result);
 .as-console-wrapper { max-height: 100% !important; top: 0; }

如果您不知道總指標。 您可以創建一組指標並在輸出對象中為每個指標創建屬性

 const users = [[1, "Sally"], [2, "Bob"], [3, "George"]], metrics = [[1, "sales", 5000], [1, "sales", 1000], [3, "missed", 1000], [2, "sales", 1000]], output = {}, allMetrics = new Set(), metricMap = {} for (const [id, metric, value] of metrics) { allMetrics.add(metric); metricMap[id] ??= {} metricMap[id][metric] ??= 0 metricMap[id][metric] += value } for (const [id, name] of users) { output[name] = { id, metrics: {} } for (const m of allMetrics) output[name].metrics[m] = metricMap[id][m] ?? 0 } console.log(output)

您可以使用Array.reduceObject.fromEntries以更實用的方式進行

 const users = [[1, "Sally"], [2, "Bob"], [3, "George"]]; const metrics = [[1, "sales", 5000], [1, "sales", 1000], [3, "missed", 1000], [2, "sales", 1000]] const usersDictonary = Object.fromEntries(users) const output = metrics.reduce((res, [id, key, value]) => { const user = usersDictonary[id] const existing = res[user] || {id, metrics:{sales: 0, missed: 0}} existing.metrics[key] = value + existing.metrics[key] return { ...res, [user]: existing } }, {}) console.log(output)

我的方法是進行幾次簡單的轉換,直到我們達到目標狀態。

 const combine = (users, metrics, types = [...new Set(metrics.map (([_, t]) => t))]) => Object .fromEntries (Object .entries (metrics .reduce ( (a, [id, type, value]) => {a [id] .metrics [type] += value; return a}, users .reduce ((a, [id, name]) => { a [id] = {name, metrics: Object .fromEntries (types .map (t => [t, 0]))} return a }, {}) )) .map (([id, {name, ...rest}]) => [name, {id: Number (id), ...rest}])) const users = [[1, "Sally"], [2, "Bob"], [3, "George"]] const metrics = [[1, "sales", 5000], [1, "sales", 1000], [3, "missed", 1000], [2, "sales", 1000]] console .log (combine (users, metrics))
 .as-console-wrapper {max-height: 100% !important; top: 0}

我們可以將其視為一系列轉換,其中我們看到以下步驟:

  • 使用reduce調用將users收集到以 id 為鍵的對象中,包括名稱和空白指標:

     { "1": {name: "Sally", metrics: {sales: 0, missed: 0}}, "2": {name: "Bob", metrics: {sales: 0, missed: 0}}, "3": {name: "George", metrics: {sales: 0, missed: 0}} }
  • 使用另一個reduce調用來添加來自metrics的真實指標數據:

     { "1": {name: "Sally", metrics: {sales: 6000, missed: 0}}, "2": {name: "Bob", metrics: {sales: 1000, missed: 0}}, "3": {name: "George", metrics: {sales: 0, missed: 1000}} }
  • 使用Object .entries將其轉換為數組條目:

     [ ["1", {name: "Sally", metrics: {sales: 6000, missed:0}}], ["2", {name: "Bob", metrics: {sales: 1000, missed: 0}}], ["3", {name: "George", metrics: {sales:0, missed: 1000}}] ]
  • map這些以重新格式化它們,使其看起來更像我們的目標格式:

     [ ["Sally", {id: 1, metrics: {sales: 6000, missed:0}}], ["Bob", {id: 2, metrics: {sales: 1000, missed: 0}}], ["George", {id: 3, metrics: {sales:0, missed: 1000}}] ]
  • 使用Object.fromEntries將它們轉回一個對象:

     { Sally: {id: 1, metrics: {sales: 6000, missed:0}}, Bob: {id: 2, metrics: {sales: 1000, missed: 0}}, George: {id: 3, metrics: {sales:0, missed: 1000}} }

我們應該注意, types是從實際指標中提取的,因此我們不會硬編碼salesmissed 我們在這里沒有做一個小的性能優化: types參數只是一個字符串數組( ['sales', 'missed'] )但是當我們使用它來創建我們的指標對象時,我們首先映射它( types .map (t => [t, 0]) ),然后在結果上調用Object .fromEntries 我們沒有在其他任何地方使用原始類型名稱,因此我們可以預先進行映射,並且只在單個項目上調用forEntries 我懷疑這將是一個嚴重的問題,但如果您願意,只需將該映射調用移至types定義的末尾即可。 (請注意,我們不能fromEntries調用移到那里,因為這樣記錄將通過引用共享相同的metrics屬性。

另請注意,我們確實假設所有指標條目都有相應的用戶條目。 如果這可能失敗,我們將不得不做一些更復雜的事情以避免增加他們不存在的指標,或者做一些其他事情來報告數據不匹配。 我們把它留給讀者作為練習。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

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