Groupby и агрегированный подсчет, принимая массив в качестве ключевого ввода в javascript

#javascript #arrays #object #group-by

#javascript #массивы #объект #группировать по

Вопрос:

У меня есть массив объектов, скажем, данных. Я хочу сгруппировать этот массив объектов на основе другого массива, скажем, arr, а также получить накопленный подсчет и получить выходные данные для каждого из элементов массива в качестве ключа. Переменная данных

 const data = [
  {
    "a":"A1",
    "b":"B2",
    "c": "C1",
    "count": 10
  },
  {
    "a":"A1",
    "b":"B1",
    "c": "C2",
    "count": 20
  },
  {
    "a":"A1",
    "b":"B2",
    "c": "C1",
    "count": 50
  },
  {
    "a":"A2",
    "b":"B1",
    "c": "C2",
    "count": 60
  },
  {
    "a":"A2",
    "b":"B2",
    "c": "C2",
    "count": 30
  },
];
  

Переменная arr

 const arr = ["a","b","c"];
  

Результат вывода должен быть

 const result = [
  [
    {
      "key":"a",
      "value":"A1",
      "count": 80
    },
    {
      "key":"a",
      "value":"A2",
      "count": 90
    }
  ],
  [
    {
      "key":"b",
      "value":"B1",
      "count": 80
    },
    {
      "key":"b",
      "value":"B2",
      "count": 90
    }
  ],
  [
    {
      "key":"c",
      "value":"C1",
      "count": 60
    },
    {
      "key":"c",
      "value":"C2",
      "count": 110
    }
  ]
];

  

Я попробовал приведенную ниже функцию, но я не могу сгруппировать и получить накопленный подсчет.

 const groupBy = (array, key) => {
  return key.map(keyl => {
  return array.reduce((result, currentValue) => {
      (result[keyl] = result[keyl]|| []).push(
        {"key":keyl,"value": currentValue[keyl],"count":currentValue["count"]}
      );
      
      return resu<
    }, {}); 
    })
  
};
const groupByAndCount = groupBy(data, arr);
console.log("groupByAndCount",groupByAndCount)
  

Ответ №1:

 const data = [{
    a: "A1",
    b: "B2",
    c: "C1",
    count: 10
  },
  {
    a: "A1",
    b: "B1",
    c: "C2",
    count: 20
  },
  {
    a: "A1",
    b: "B2",
    c: "C1",
    count: 50
  },
  {
    a: "A2",
    b: "B1",
    c: "C2",
    count: 60
  },
  {
    a: "A2",
    b: "B2",
    c: "C2",
    count: 30
  }
];

const arr = ["a", "b", "c"];
const groupBy = (array, key) => {
  return key.map((keyl) => {
    return array.reduce((result, item) => {
      const temp = result.filter((it) => it.key === keyl amp;amp; it.value === item[keyl])[0]
      if (temp) {
        temp["count"] = temp["count"]   item.count;
      } else {
        const obj = {};
        obj.key = keyl;
        obj.value = item[keyl];
        obj.count = item.count;
        result.push(obj);
      }
      return result
    }, []);
  });
};
const groupByAndCount = groupBy(data, arr);
console.log("groupByAndCount", groupByAndCount);  

Ответ №2:

Вы можете использовать этот подход O (n2), который использует функцию Array.prototype.reduce для группировки и функцию Object.values для извлечения сгруппированных объектов.

 const data = [  {    "a":"A1",    "b":"B2",    "c": "C1",    "count": 10  },  {    "a":"A1",    "b":"B1",    "c": "C2",    "count": 20  },  {    "a":"A1",    "b":"B2",    "c": "C1",    "count": 50  },  {    "a":"A2",    "b":"B1",    "c": "C2",    "count": 60  },  {    "a":"A2",    "b":"B2",    "c": "C2",    "count": 30  }],
      arr = ["a","b","c"],
      result = Object.values(Object.values(data.reduce((r, {count, ...c}) => {
        arr.forEach(k => {
          (r[c[k]] || (r[c[k]] = {key: k, value: c[k], count: 0})).count  = count;
        });

        return r;
      }, Object.create(null)))
          .reduce((r, {key, ...rest}) => {
            (r[key] || (r[key] = [])).push({key, ...rest});
            return r;
          }, Object.create(null)));

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