Jak součet hodnoty ekvivalentní klíče do pole objektů, kde může být více, nově vygenerované klíče?

0

Otázka

Existuje řada objektů, tak jako tam, kde je "kategorie" klíč a nějaké "série" klíče.

arrOne = [
    {
        "series_1": 25,
        "category": "Category 1",
        "series_2": 50
    },
    {
        "series_1": 11,
        "category": "Category 2",
        "series_2": 22
    },
    {
        "series_1": 32,
        "category": "Category 1",
        "series_2": 74
    },
    {
        "series_1": 74,
        "category": "Category 3",
        "series_2": 98
    },
    {
        "series_1": 46,
        "category": "Category 3",
        "series_2": 29
    },

]

(Všimněte si, že "kategorie" můžete být skoro žádnou hodnotu, i když tam bude pravděpodobně více podobné hodnoty, stejně jako některé jedinečné hodnoty, např. existuje více objektů s 'kategorie' hodnota 'Kategorie 3, ale pouze 1 s 'kategorie' hodnota 'Kategorie 2')

Následující řádky kódu budou sčítat všechny series_1 pro objekty s stejné kategorii

        var objForAllCategories = {};
        this.arrOne.forEach(item => {
            if (objForAllCategories.hasOwnProperty(item.category))
                objForAllCategories[item.category] = objForAllCategories[item.category] + item.series_1;
            else
                objForAllCategories[item.category] = item.series_1;
        });
        for (var prop in objForAllCategories) {
            this.allCategoriesAndValues.push({ 
                category: prop, 
                series_1: objForAllCategories[prop] 
            });
        }

Tak to by mělo za následek:

allCategoriesAndValues = [
    {
        "category": "Category 1",
        "series_1": 57       // 25 + 32 adding up series_1 from all 'Category 1' items in arrOne
    },
    {
        "category": "Category 2",
        "series_1": 11      // only 1 'Category 2' from arrOne
    },
    {
        "category": "Category 3",
        "series_1": 120     // 74 + 46 adding up series_1 from all 'Category 3' items in arrOne
    }
]

Nicméně, chci, aby bylo možné přidávat nejen series_1, ale i všechny ostatní položky.

Tento příklad má pouze kategorie a series_1 a series_2 jako klíče. Nicméně, tam by mohlo být:

  1. series_3
  2. series_4
  3. series_5
  4. series_6
  5. series_7
  6. atd..

Jak mohu účet pro všechny potenciální series_x?

Zamýšleným výsledkem:

allCategoriesAndValues = [
    {
        "category": "Category 1",
        "series_1": 57,
        "series_2": 124,
        ..... if 'series_3', 'series_4' etc. existed, it would be included in this as above
    },
    {
        "category": "Category 2",
        "series_1": 11,
        "series_2": 22,
        ..... if 'series_3', 'series_4' etc. existed, it would be included in this as above
    },
    {
        "category": "Category 3",
        "series_1": 120,
        "series_2": 127,
        ..... if 'series_3', 'series_4' etc. existed, it would be included in this as above
    }
]
arrays javascript json key-value
2021-11-24 02:19:06
6

Nejlepší odpověď

2

Zvládnout více vlastností logiky, můžete procházet každý majetek, a zkontrolujte, zda to odpovídá regulárnímu výrazu series_\d+. Pokud ano, víte, že to je vlastnost, které potřebujete, aby přírůstek, a s ní zacházet odpovídajícím způsobem (vlastnost existence zkontrolujte, zda je rovněž nezbytné, jak poukázal Jayce444).

Následující řešení využívá Array.reduce. V reduktoru funkce, kontroluje, zda je akumulátor pole obsahuje položku se stejným category majetek jako ten v současné době je smyčka přes. Pokud ano, bude přírůstek odpovídající vlastnosti. Jinak to bude tlačit aktuální položky na zásobníku pole.

arrOne=[{series_1:25,category:"Category 1",series_2:50},{series_1:11,category:"Category 2",series_2:22},{series_1:32,category:"Category 1",series_2:74},{series_1:74,category:"Category 3",series_2:98},{series_1:46,category:"Category 3",series_2:29,series_3:50}];

const res = arrOne.reduce((a, b) => {
  let found = a.find(e => e.category == b.category)
  if (found) {
    Object.keys(b).forEach(e => {
      if (/series_\d+/g.test(e)) found[e] = found[e] ? found[e] + b[e] : b[e];
    })
  } else {
    a.push(b)
  }
  return a;
}, [])

console.log(res)

2021-11-24 02:38:52

Tento přístup přeruší, když všechny objekty nemají stejné série klíče. Například, pokud přidáte series_3: 5 na první objekt pouze, skončí jako series_3: NaN ve výsledku.
Jayce444

Nebude chybět nová série klíče přidány pro stejnou kategorii v novější objekty? To je také O(n^2) (myslím)
Phil

@Phil Díky za upozornění. Aktualizoval jsem svou odpověď.
Spectric
1

Něco takového by mohlo fungovat.

arrOne = [ { "series_1": 25, "category": "Category 1", "series_2": 50 }, { "series_1": 11, "category": "Category 2", "series_2": 22 }, { "series_1": 32, "category": "Category 1", "series_2": 74 }, { "series_1": 74, "category": "Category 3", "series_2": 98 }, { "series_1": 46, "category": "Category 3", "series_2": 29 },];

const result = [];
arrOne.reduce((acc, {category, ...series}) => {
  if (acc.has(category)) {
    Object.entries(series).forEach(([key, value]) => {
      if (key.startsWith('series_')) {
        acc.get(category)[key] = (acc.get(category)[key] || 0) + value;
      }
    });
  } else {
    const item = {category, ...series};
    result.push(item);
    acc.set(category, item);
  }
  return acc;
}, new Map());

console.log(result);

2021-11-24 02:27:40

Nejste si jisti, o reduktor s vedlejšími účinky (result mutace)
Phil
0

Vytvořit Mapu pro kompletaci série částky podle kategorie.

Pak vytvořit pole z mapy s klíči jako category

const arr1 = [{"series_1":25,"category":"Category 1","series_2":50},{"series_1":11,"category":"Category 2","series_2":22},{"series_1":32,"category":"Category 1","series_2":74},{"series_1":74,"category":"Category 3","series_2":98},{"series_1":46,"category":"Category 3","series_2":29}]

const t1 = performance.now()

const cats = arr1.reduce((map, { category, ...series }) =>
  map.set(category, Object.entries(series)
    .reduce((s, [ key, count ]) => ({
      ...s,
      [ key ]: (s[key] ?? 0) + count
    }), map.get(category) ?? {})
  ), new Map())

const allCategoriesAndValues = Array.from(cats, ([ category, series ]) => ({
  category,
  ...series
}))

const t2 = performance.now()

console.info(allCategoriesAndValues)
console.log(`Took ${t2 - t1}ms`)
.as-console-wrapper { max-height: 100% !important; }

2021-11-24 02:32:20
0

Udělám to takto...

const arrOne = 
  [ { series_1: 25, category: 'Category 1', series_2: 50 } 
  , { series_1: 11, category: 'Category 2', series_2: 22 } 
  , { series_1: 32, category: 'Category 1', series_2: 74 } 
  , { series_1: 74, category: 'Category 3', series_2: 98 } 
  , { series_1: 46, category: 'Category 3', series_2: 29 } 
  ] 

console.time('chrono')

const allCategoriesAndValues =
  Object.entries(
  arrOne.reduce((r,{ category, ...series })=>
    {
    let cat = r[category] = r[category] ?? {} 
    Object.entries(series).forEach(([sName,val]) => cat[sName] = (cat[sName] ?? 0) + val);
    return r
    },{})
  ).map(([category,series])=>({category,...series}))

console.timeEnd('chrono')

console.log( allCategoriesAndValues )
.as-console-wrapper {max-height: 100%!important;top:0 }

2021-11-24 02:47:52
0

Prostě můžeš iterovat přes pole objektů a pak klíče každý objekt, ukládání do vyrovnávací paměti objektu. Stačí buď zkontrolovat existenci každý klíč a přidejte jej, pokud chybí, nebo můžete prostě splývají falsey klíče do výchozí hodnoty, jako já. Odstranit kategorii klíče od objektu, poté, co jsem si jeho hodnotu, takže se nemusím snažit přeskočit během klíčové iterace.

const arrOne = [
  {"series_1": 25, "category": "Category 1", "series_2": 50},
  {"series_1": 11, "category": "Category 2", "series_2": 22},
  {"series_1": 32, "category": "Category 1", "series_2": 74},
  {"series_1": 74, "category": "Category 3", "series_2": 98},
  {"series_1": 46, "category": "Category 3", "series_2": 29},
];

let buffer = {};
arrOne.forEach(i=>{
  let c = i.category;
  buffer[c] = buffer[c] || {};
  delete i.category;
  Object.keys(i).forEach(k=>{
    buffer[c][k] = buffer[c][k] || 0;
    buffer[c][k] += i[k];
  });
});

console.log(buffer);

let final = Object.keys(buffer).map(k=>{return {[k]: buffer[k]}});
console.log(final);

Pokud nepotřebujete mít to v poli, poslední krok je volitelný. Existuje pouze k transformaci objektu do pole.

2021-11-24 02:31:18
0

Zde je, jak bych to udělal

const res = arrOne.reduce((acc, { category, ...vals }) => {
    if (acc[category]) {
        Object.entries(vals).forEach(([ key, val ]) => acc[category][key] = acc[category][key] ? acc[category][key] + val : val);

    } else {
        acc[category] = vals;

    }

    return acc;
}, {});
2021-11-24 03:11:13

V jiných jazycích

Tato stránka je v jiných jazycích

Русский
..................................................................................................................
Italiano
..................................................................................................................
Polski
..................................................................................................................
Română
..................................................................................................................
한국어
..................................................................................................................
हिन्दी
..................................................................................................................
Français
..................................................................................................................
Türk
..................................................................................................................
Português
..................................................................................................................
ไทย
..................................................................................................................
中文
..................................................................................................................
Español
..................................................................................................................
Slovenský
..................................................................................................................