简体   繁体   中英

how would i aggregate array of objects into groups, dynamically

I have some dynamic data. Assume that id will always be present, and the other key:values will change.

I am trying to wrap my head around an abstract approach, but I don't think I know enough about the tools I have available.

I am looking for an approach to aggregate dynamically.

example, if I have this data:

const dataum = [{
  "id": 1,
  "q1": "yes",
  "q2": 4,
  "q3": null
}, {
  "id": 2,
  "q1": null,
  "q2": 14,
  "q3": "medium"
}, {
  "id": 3,
  "q1": "no",
  "q2": 83,
  "q3": "high"
}, {
  "id": 27,
  "q1": "yes",
  "q2": 62,
  "q3": null
}]

and am attempting to create something like this:

const aggData = [{
  "q1": {
    "yes": 2,
    "empty": 1,
    "no": 1
  }
}, {
  "q2": {
    "0to60": 2,
    "60to70": 1,
    "70to100": 1,
    "empty": 0
  }
} {
  "q3": {
    "medium": 1,
    "empty": 2,
    "high": 1
  }
}]

I haven't tried much. because I am stuck at the outer most process / function. I have thought about for() .keys and .values, I have looked at array.reduce() ... but I still do not get how to be able to dynamically say: newObject.key.someAnswer += 1 where the key is dynamic, and the answer is dynamic (or null).

I wouldn't worry too much about the ranges... I think with a tiny bit of help I can fork the process.

I can provide some more data to this process, in any format, like:

const qProperties = [{
  "q1": {
    "type": "YN",
    "values": ["yes", "no"]
  }
}, {
  "q3": {
    "type": "LMH",
    "values": ["low", "medium", "high"]
  }
}]

If it would help reduce the code footprint, make it more abstract.

Although your input data does not really match your expected output data (which is probably why you got the downvote), I think you want something like that:

const dataum = [
  { id: 1, q1: "yes", q2: 4, q3: null },
  { id: 2, q1: null, q2: 14, q3: "medium" },
  { id: 3, q1: "no", q2: 83, q3: "high" },
  { id: 27, q1: "yes", q2: 62, q3: null },
];
const intermediate1 = dataum.reduce((acc, curr) => {
  Object.entries(curr).forEach(([k,v]) => {
    if (k !== "id") {
      if (!acc[k]) {
        acc[k] = [];
      }
      acc[k].push(v);
    }
  });
  return acc;
}, {});

console.log(intermediate1);
// {
//   q1: [ 'yes', null, 'no', 'yes' ],
//   q2: [ 4, 14, 83, 62 ],
//   q3: [ null, 'medium', 'high', null ]
// }

const final = Object.entries(intermediate1).reduce((acc, [k, v]) => {
  const accumulated = v.reduce((inner_acc, inner_val) => {
    if (inner_val === null) {
      inner_val = "empty";
    }
    if (!inner_acc[inner_val]) {
      inner_acc[inner_val] = 0;
    }
    inner_acc[inner_val] += 1;
    return inner_acc;
  }, {});    
  acc.push({
    [k]: accumulated,
  });
  return acc;
}, []);

console.log(final);      
// [
//   { q1: { yes: 2, empty: 1, no: 1 } },
//   { q2: { '4': 1, '14': 1, '62': 1, '83': 1 } },
//   { q3: { empty: 2, medium: 1, high: 1 } }
// ]

You may want to have a look into lodash, maybe they have something like that already.

You could use lodash.groupby if you're not bothered about the implementation.

https://www.npmjs.com/package/lodash.groupby

const groupBy = require('lodash.groupby');

const keys = ["q1", "q2", "q2"];
const dataum = [
  { id: 1, q1: "yes", q2: 4, q3: null },
  { id: 2, q1: null, q2: 14, q3: "medium" },
  { id: 3, q1: "no", q2: 83, q3: "high" },
  { id: 27, q1: "yes", q2: 62, q3: null }
];

const grouped = [];

function countKeys(object) {
  const counts = [];
  const keys = Object.keys(object);

  keys.forEach((key) => {
    const count = Object.values(object[key]).length;
    counts.push({ [key]: count });
  });

  return counts;
}

keys.forEach((key) => {
  const groups = _.groupBy(dataum, key);
  const counts = countKeys(groups);
  const groupedRow = { [key]: counts };
  grouped.push(groupedRow);
});

console.log(grouped);

// const output = [
//   { q1: [{ yes: 2 }, { null: 1 }, { no: 1 }] },
//   { q2: [{ "4": 1 }, { "14": 1 }, { "62": 1 }, { "83": 1 }] },
//   { q2: [{ "4": 1 }, { "14": 1 }, { "62": 1 }, { "83": 1 }] }
// ];

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM