Home > OS >  Sum all similar keys in an array with a random number of keys and array items
Sum all similar keys in an array with a random number of keys and array items

Time:06-22

My Array (can have several items, and there can be multiple 'keys' other than 'companyName'):

myarray = [
    { companyName: 'X', randomKey: 10, randomKey2: 90, ...},
    { companyName: 'X', randomKey: 30, randomKey2: 81, ...},
    { companyName: 'X', randomKey: 930, randomKey2: 93, ...},
    { companyName: 'X', randomKey: 20, randomKey2: 23, ...},
    { companyName: 'X', randomKey: 10, randomKey2: 10, ...},
    { companyName: 'X', randomKey: 11, randomKey2: 40, ...},
    ....
]

randomKey and randomKey2 are only examples. The key names can be anything and there can be 1 or more in each array item.

Expected results:

[
    { companyName: 'X', randomKey: 1011, randomKey2: 337, ...},
]

companyName: 'X' is a fixed value, and all of the items have this

Attempted:

   this.myarray.reduce((acc, curr) => {
      let ind = b.findIndex(e => e.companyName === curr.companyName);
      if (ind > -1) {
          acc[ind][c] =  acc[ind][c]    a[c]
      } else {
          a[c] =  a[c] || 0
         acc.push(curr)
      }
      return b;
   }, []);

But it leads to [{x: NaN}].

How can I fix this?

CodePudding user response:

As to why your code is not working: you're not iterating over the object keys anywhere. There is reference to a variable c, but it's never defined.

Probably easier to reduce to an accumulator object first:

const data = [
    { companyName: 'X', randomKey: 10, randomKey2: 90 },
    { companyName: 'X', randomKey: 30, randomKey2: 81 },
    { companyName: 'X', randomKey: 930, randomKey2: 93 },
    { companyName: 'X', randomKey: 20, randomKey2: 23 },
    { companyName: 'X', randomKey: 10, randomKey2: 10 },
    { companyName: 'X', randomKey: 11, randomKey2: 40 },
];

const fn = (data) => Object.values(
  data.reduce((a, {companyName, ...rest}) => {
    const entry = a[companyName] ??= { companyName }; 
    Object.entries(rest).forEach(([k, v]) => entry[k] = (entry[k] ?? 0)   v);
    return a;
  }, {})
);

console.log(fn(data));

CodePudding user response:

You can play around with this example

const myArray = [
    { companyName: 'X', randomKey: 10, randomKey2: 90 },
    { companyName: 'X', randomKey: 30, randomKey2: 81 },
    { companyName: 'X', randomKey: 930, randomKey2: 93 },
    { companyName: 'X', randomKey: 20, randomKey2: 23 },
    { companyName: 'X', randomKey: 10, randomKey2: 10 },
    { companyName: 'X', randomKey: 11, randomKey2: 40 },
    { companyName: 'Y', randomKey: 11, randomKey2: 45, randomKey3: 4 },
    { companyName: 'Y', randomKey: 21, randomKey2: 46 },
];

const results = {};

const addKeyValue = (target, data) => {
  const keys = [...new Set([...Object.keys(target), ...Object.keys(data)])];

  keys.forEach((key) => {
    target[key] = target[key] || 0;
    target[key]  = data[key] || 0;
  });

  return target;
};

myArray.forEach(({ companyName, ...data }) => {
  if (results[companyName] === undefined) {
    results[companyName] = { ...data };
  } else {
    results[companyName] = addKeyValue(results[companyName], data);
  }
});

console.log(results);

https://jsfiddle.net/gre6Ly1a/1/

CodePudding user response:

myarray = [
  { companyName: 'X', randomKey: 10, randomKey2: 90},
  { companyName: 'X', randomKey: 30, randomKey2: 81},
  { companyName: 'X', randomKey: 930, randomKey2: 93},
  { companyName: 'X', randomKey: 20, randomKey2: 23},
  { companyName: 'X', randomKey: 10, randomKey2: 10},
  { companyName: 'X', randomKey: 11, randomKey2: 40}
]

const b = myarray.reduce((acc, curr)=>{
  let properties = {};
    for(let key in curr){
    if(acc[key] && acc[key] !== 'X') properties[key] = acc[key] curr[key]
    }
    return {...acc, ...curr, ...properties}
}, {})

console.log(b)

As already stated, it would probably be easier to ensure that the accumulator is initially an object. But this example will also work like the others above

CodePudding user response:

Presented below is one possible way to achieve the desired objective.

Code Snippet

const myTransform = (arr, col) => (
  Object.values(      // extract only values from the result below
    arr.reduce(       // use ".reduce()" to iterate over the array
      (acc, itm) => {       // "acc" is the accumulator, "itm" is the iterator
        const k = itm[col] || null;     // gather the "key" (ie, "X" from "companyName")
        acc[k] ??= { [col]: k };        // set-up accumulator for "X"
        Object.entries(itm)             // iterate over the "itm"
        .filter(([key, _]) => key !== col)      // discard "companyName" 
        .forEach(([key, val]) => {      // sum each key from "itm" into accumulator
          acc[k][key] ??= 0;            // initialize accumulator "X.randomKey/2" to 0
          acc[k][key]  =  val;          // transform "val" into a number (ie,  val) & add
        });
        return acc;         // return the accumulator at each iteration
      },
      {}                    // initialize the accumulator as an empty object
    )
  )                 // implicit return of the values array
);

const myArray = [
    { companyName: 'X', randomKey: 10, randomKey2: 90},
    { companyName: 'X', randomKey: 30, randomKey2: 81},
    { companyName: 'X', randomKey: 930, randomKey2: 93},
    { companyName: 'X', randomKey: 20, randomKey2: 23},
    { companyName: 'X', randomKey: 10, randomKey2: 10},
    { companyName: 'X', randomKey: 11, randomKey2: 40},
];

console.log(myTransform(myArray, 'companyName'));

console.log(
  'test case 2 - with updated input array\n',
  myTransform(
    myArray.concat([
      { companyName: 'Y', randomKey: 100, randomKey4: 60},
      { companyName: 'Y', randomKey: 101, randomKey4: 141}
    ]),
    'companyName'
  )
);
.as-console-wrapper { max-height: 100% !important; top: 0 }

Explanation

Inline comments added to the snippet above.

CodePudding user response:

    const data = [
        { companyName: 'X', randomKey: 10, randomKey2: 90 },
        { companyName: 'X', randomKey: 30, randomKey2: 81 },
        { companyName: 'X', randomKey: 930, randomKey2: 93 },
        { companyName: 'X', randomKey: 20, randomKey2: 23 },
        { companyName: 'X', randomKey: 10, randomKey2: 10 },
        { companyName: 'X', randomKey: 11, randomKey2: 40 },
    ];
    
    
    
    let k;
    const agg = data.map((o) => Object.keys(o).map((key) => {return {[key]:o[key]};})).flat().reduce((a,b) => {
      k = Object.keys(b)[0];
      a[k] = a[k] ? a[k]   b[k] : b[k];
      return a;
    })
    
    console.log(agg);

  • Related