Comment la somme des valeurs de l'équivalent de clés dans un tableau d'objets pour lesquels il peut y avoir plusieurs, nouvellement créées, les clés?

0

La question

Il existe un tableau d'objets comme s'il y a une "catégorie" de la clé et de certains de la série des "clés".

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
    },

]

(Notez que "catégorie" peut être à peu près n'importe quelle valeur, mais il y aura probablement plusieurs des valeurs similaires ainsi que certaines valeurs uniques par exemple, il y a plusieurs objets à la "catégorie" valeur "Catégorie 3" mais seulement 1 avec 'catégorie' valeur 'de la Catégorie 2')

Les lignes de code suivantes seront toutes series_1 pour les objets de la même catégorie

        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] 
            });
        }

Donc il aura les résultats suivants:

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
    }
]

Cependant, je veux être en mesure d'ajouter non seulement series_1 mais aussi tous les autres éléments.

Cet exemple n'a catégorie et series_1 et series_2 que les clés. Toutefois, il pourrait y avoir:

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

Comment puis-je tenir compte de toutes les series_x?

Résultat prévu:

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

La meilleure réponse

2

Pour gérer les multiples propriétés de la logique, vous pouvez parcourir chaque propriété et de vérifier si cela correspond à l'expression rationnelle series_\d+. Si c'est le cas, vous savez que c'est une propriété que vous devez incrémenter, et de les traiter en conséquence (une propriété existence de vérification est également nécessaire, comme l'a souligné Jayce444).

La solution suivante utilise Array.reduce. Dans le réducteur de la fonction, il vérifie si l'accumulateur tableau contient un élément avec la même category bien que déjà bouclé. Si elle le fait, elle augmente les propriétés appropriées. Sinon, il va pousser l'élément courant de l'accumulateur tableau.

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

Cette approche des pauses lorsque tous les objets n'ont pas la même série de touches. Par exemple, si vous ajoutez series_3: 5 pour premier objet, il finit series_3: NaN dans le résultat.
Jayce444

Ne pas cette miss nouvelle série de clés ajoutées pour la même catégorie, au plus tard dans les objets? C'est également en O(n^2) (je pense)
Phil

@Phil Merci pour l'avis. J'ai mis à jour ma réponse.
Spectric
1

Quelque chose comme cela pourrait fonctionner.

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

Pas sûr au sujet d'un réducteur à des effets secondaires (result la mutation)
Phil
0

Créer une Carte de rassembler série montants par catégorie.

Ensuite, créer un tableau à partir de ce plan avec les touches 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

Je vais faire ça de cette façon...

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

Vous pouvez simplement effectuer une itération sur le tableau d'objets, puis les touches de chaque objet, de les stocker dans une mémoire tampon de l'objet. Vous avez juste à vérifier l'existence de chaque touche et l'ajouter si elle est manquante, ou vous pouvez simplement fusionner falsey clés en une valeur par défaut, comme je l'ai fait. J'ai supprimer la clé de catégorie à partir de l'objet après je reçois de sa valeur, de sorte que je n'ai pas à essayer de l'ignorer lors de la clé de l'itération.

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);

Si vous n'avez pas besoin d'avoir ceci dans un tableau, la dernière étape est facultative. Il n'existe pour transformer l'objet dans un tableau.

2021-11-24 02:31:18
0

Voici comment j'allais le faire

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

Dans d'autres langues

Cette page est dans d'autres langues

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