Birden çok yeni oluşturulan anahtarın olabileceği bir nesne dizisindeki eşdeğer anahtarların değerleri nasıl toplanır?

0

Soru

Bir 'kategori' anahtarının ve bazı 'seri' anahtarlarının bulunduğu so gibi bir dizi nesne vardır.

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

]

('Kategori' nin hemen hemen her değer olabileceğini unutmayın, ancak muhtemelen birden fazla benzer değerin yanı sıra bazı benzersiz değerler de olacaktır, örneğin 'kategori' değeri 'Kategori 3' olan birden çok nesne vardır, ancak 'kategori' değeri 'Kategori 2'olan yalnızca 1)

Aşağıdaki kod satırları, aynı kategoriye sahip nesneler için series_1'in tümünü ekleyecektir

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

Bu yüzden sonuçlanır:

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

Ancak, sadece series_1 değil, diğer tüm öğeleri de ekleyebilmek istiyorum.

Bu örnekte yalnızca kategori ve series_1 ve series_2 tuşları bulunur. Ancak, olabilir:

  1. seriler_3
  2. seriler_4
  3. seriler_5
  4. series_6
  5. seriler_7
  6. vb..

Tüm potansiyel series_x'leri nasıl açıklayabilirim?

Amaçlanan sonuç:

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

En iyi cevabı

2

Birden çok özellik mantığını işlemek için, her özellik arasında döngü yapabilir ve regex ile eşleşip eşleşmediğini kontrol edebilirsiniz series_\d+. Eğer öyleyse, bunun artırmanız gereken bir özellik olduğunu ve buna göre işlemeniz gerektiğini bilirsiniz (Jayce444 tarafından belirtildiği gibi bir özellik varlığı kontrolü de gereklidir).

Aşağıdaki çözüm kullanırArray.reduce. Redüktör fonksiyonunda, akümülatör dizisinin aynı öğeye sahip bir öğe içerip içermediğini kontrol eder category şu anda ilmekli olan özellik. Bunu yaparsa, uygun özellikleri artıracaktır. Aksi takdirde, geçerli öğeyi akümülatör dizisine itecektir.

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

Tüm nesneler aynı seri anahtarlara sahip olmadığında bu yaklaşım bozulur. Örneğin, eklerseniz series_3: 5 sadece ilk nesneye, şu şekilde sonuçlanır series_3: NaN sonuç olarak.
Jayce444

Bu, daha sonraki nesnelerde aynı kategori için eklenen yeni seri anahtarlarını kaçırmaz mı? Aynı zamanda O (n^2) (Sanırım)
Phil

@ Phil Bildirim için teşekkürler. Cevabımı güncelledim.
Spectric
1

Böyle bir şey işe yarayabilir.

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

Yan etkileri olan bir redüktörden emin değilim (result mutasyon)
Phil
0

Seri toplamlarını kategoriye göre harmanlamak için bir Harita oluşturun.

Ardından, bu haritadan aşağıdaki gibi tuşlarla bir dizi oluşturun 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

Bu şekilde yapacağım...

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

Bir nesne dizisini ve ardından her nesnenin anahtarlarını bir arabellek nesnesine depolayarak yineleyebilirsiniz. Sadece her bir anahtarın varlığını kontrol etmeli ve eksikse eklemelisiniz ya da falsey anahtarlarını benim yaptığım gibi varsayılan bir değere birleştirebilirsiniz. Değerini aldıktan sonra kategori anahtarını nesneden kaldırıyorum, böylece anahtar yineleme sırasında atlamaya çalışmam gerekmiyor.

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

Bunu bir dizide bulundurmanız gerekmiyorsa, son adım isteğe bağlıdır. Yalnızca nesneyi bir diziye dönüştürmek için vardır.

2021-11-24 02:31:18
0

İşte bunu nasıl yapacağım

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

Diğer dillerde

Bu sayfa diğer dillerde

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