簡體   English   中英

通過 object 類別為多個 arrays 查找深度嵌套數組數據的總和

[英]Finding the sum of deeply nested array data by object category for multiple arrays

我有一個 function,它返回 2 個單獨的 arrays,其中包含 2 個 arrays。

[Array(3), Array(3)]

[Array(3), Array(3)]

那些嵌套的 arrays 每個包含 6 個對象

{value: "10.50", category: "a"}, 
{value: "55.50", category: "a"}
{value: "10.50", category: "b"}, 
{value: "35.50", category: "b"},
{value: "15.50", category: "c"},
{value: "45.50", category: "c"}

我正在嘗試遍歷每個主要的 2 arrays 並按如下類別返回嵌套 arrays 的總和值: 請記住,該值當前是一個字符串。

[
 [
  {value: "66.00", category: "a"},
  {value: "46.00", category: "b"},
  {value: "61.00", category: "c"},
 ]
]

我已經嘗試了下面的方法,但似乎無法做到正確,我查看了許多 SO 線程,我知道有很多類似的線程,但到目前為止沒有什么對我有用。 TIA。

我可憐的嘗試。

  const x = array.forEach((data) => {
    data.reduce(function (
      acc: any[],
      val: { category: string; value: string }
    ) {
      const o = acc
        .filter(function (obj) {
          return obj.category === val.category;
        })
        .pop() || { category: val.category, value: 0 };

      o.value += parseFloat(String(val.value));
      acc.push(o);
      return acc;
    },
    []);
  });

聽起來您只需要分組為由category索引的 object ,將值相加,確保將字符串強制轉換為數字,然后將其轉換回對象數組:

 const outerArr = [ [ {value: "10.50", category: "a"}, {value: "55.50", category: "a"}, {value: "10.50", category: "b"}, {value: "35.50", category: "b"}, {value: "15.50", category: "c"}, {value: "45.50", category: "c"} ], // etc ]; const final = outerArr.map((subarr) => { const grouped = {}; for (const { value, category } of subarr) { grouped[category] = (grouped[category] || 0) + Number(value); } return Object.entries(grouped).map(([category, value]) => ({ value: value.toFixed(2), category })); }); console.log(final);

最終值為字符串格式,但您可以根據需要進行更改。 單個數組的示例:

Object.entries(
  arr.reduce((acc,curr)=>{
    acc[curr.category] = (acc[curr.category] || 0.0) + parseFloat(curr.value)
    return acc;
  },{})
)
.map(([a,b])=>({category:a,value:b.toFixed(2).toString()}));

您的問題還有其他幾個很好的答案,盡管我認為這個答案更短、更快且更易於理解。 (查看我的解決方案底部的工作示例)。 我們可以使用一些簡單的數組和 object 方法來實現這一點。

1. 整合數據

首先,我們會將您的每個嵌套 arrays 對象合並為單個對象,其中類別(我們的唯一值)作為鍵,以及它們的值。 我們可以使用數組reduce()方法來做到這一點。 在這里,我們將使用{}作為累加器的初始值,然后通過設置其屬性將其推送到該累加器 object。 當我們迭代時,我們會將每個值添加到關聯的類別屬性中。 如果尚未在累加器 object 上設置屬性,這可能會導致錯誤。

解決此問題的一種方法是使用三元組來檢查屬性是否存在,然后如果不存在則設置屬性,或者如果存在則添加到值中,如下所示:

// a is the accumulator, c is our category name, and v is our value
a[c] ? a[c] += parseFloat(v) : a[c] = parseFloat(v) // -> {a: 66, b: 46, c: 61}

一種更簡單的方法是使用無效合並。 空值合並將檢查該值是否為 null 或未定義,如果是,我們使用0作為當前值。 在這個方法中,我們總是設置屬性,並且只是用自身(或0 )添加到正在評估的當前值來覆蓋它,如下所示:

a[c] = (a[c] ?? 0) + parseFloat(v) // -> {a: 66, b: 46, c: 61}

在我的 reduce 方法中設置參數名稱時,我還選擇使用 object 重組,以便我可以輕松訪問所有三個變量。 但這不是必需的,因此以下任何一種方法都可以正常工作。 使用 object 解構還允許我們重命名我們的解構參數以更易於使用( c, v而不是category, value )。 要了解有關解構和重命名參數的更多信息,請查看 Wes Bos 的文章Rename & Destructure Variables in ES6

// Without Object Destructuring
arr.reduce((a, o) => (a[o.category] = (a[o.category] ?? 0) + parseFloat(o.value), a), {});

// With Object Destructuring
arr.reduce((a, {value: v, category: c}) => (a[c] = (a[c] ?? 0) + parseFloat(v), a), {});

2. 將合並的對象擴展為對象數組

一旦我們為每個對象數組獲得了簡化的 object(例如{a: 66, b: 46, c: 61} ),我們的下一個任務是將其轉換回我們開始使用但現在合並的一系列對象格式。 為此,我們首先使用Object.entries()方法將新的鍵值對 object 轉換為嵌套的 arrays 數組。 這將允許我們將數組重新映射為對象數組,在此期間我們將重寫所需的鍵名並將我們的編號值轉換回固定十進制計數為 2 的字符串。

在前面的步驟中,我們使用其屬性名稱解構了 object。 這一次,因為Object.entries()將我們的數據作為數組返回,我們將使用數組解構。 這類似於 object 解構,不同之處在於我們在重構數組時需要使用括號。 請記住始終將您的解構參數包含在括號中,否則您會收到錯誤消息:

// obj = {a: 66, b: 46, c: 61};

Object.entries(obj).map([c, v] => ({ value: v.toFixed(2), category: c }))
// !!! Uncaught SyntaxError: Malformed arrow function parameter list

Object.entries(obj).map(([c, v]) => ({ value: v.toFixed(2), category: c }))
/* -> [
        {value: "66.00", category: "a"},
        {value: "46.00", category: "b"},
        {value: "61.00", category: "c"}
      ]
*/

3. 把它們放在一起。 最終結果:

現在剩下的就是把它們放在一起:這是最終結果:

 const data = [ [ {value: "10.50", category: "a"}, {value: "55.50", category: "a"}, {value: "10.50", category: "b"}, {value: "35.50", category: "b"}, {value: "15.50", category: "c"}, {value: "45.50", category: "c"} ], // [... ] ]; const consolidate = arr => arr.map(e => Object.entries(e.reduce((a, {value: v, category: c}) => (a[c] = (a[c]?? 0) + parseFloat(v), a), {})).map(([c, v]) => ({ value: v.toFixed(2), category: c }))); console.log(consolidate(data));

暫無
暫無

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

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