Home > OS >  How does one, from a list of objects, group and collect just specific values which are explicitly re
How does one, from a list of objects, group and collect just specific values which are explicitly re

Time:01-21

I have a data structure like

const dd = [{
  keyone: "test",
  two: "you",
  three: 'op',
}, {
  keyone: "youuuu",
  two: "ttt",
  three: 'op',
}, {
  keyone: "operation",
  two: "test",
  three: 'op',
}];

And I am wanting to be able to pull out keyone and two into an object like the following

const obj = { keyone: ['test', 'youuuu', 'operation'], two: ['you', 'ttt', 'test']}

I've achieved this using two maps and combining them but I would like to use only one loop if possible.

EDIT:

I am currently using destructuring to extract values:

const mapOne = dd.map(({ keyone }) => keyone);
const mapTwo = dd.map(({ two }) => two);
const test = {
  keyone: mapOne,
  two: mapTwo,
};

CodePudding user response:

A generically implemented, thus re-usable and configurable function, which does exactly what the OP did ask for, would be close to the next provided example code ...

function groupAndCollectSpecifcEntriesOnly(collector, item) {
  const { keyList, result } = collector;

  keyList.forEach(key => {
    if (item.hasOwnProperty(key)) {

      (result[key] ??= []).push(item[key])
    }
  });
  return collector;
}

const sampleData = [{
  keyone: "test",
  two: "you",
  three: 'op',
}, {
  keyone: "youuuu",
  two: "ttt",
  three: 'op',
}, {
  keyone: "operation",
  two: "test",
  three: 'op',
}];

console.log(
  sampleData.reduce(groupAndCollectSpecifcEntriesOnly, {

    keyList: ['keyone', 'two'],
    result: {},

  }).result
);
console.log(
  sampleData.reduce(groupAndCollectSpecifcEntriesOnly, {

    keyList: ['three', 'keyone'],
    result: {},

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

CodePudding user response:

You could take an array of keys and group the values together.

const
    data = [{ keyone: "test", two: "you", three: 'op' }, { keyone: "youuuu", two: "ttt", three: 'op' }, { keyone: "operation", two: "test", three: 'op' }],
    keys = ['keyone', 'two'],
    grouped = data.reduce((r, o) => {
        keys.forEach(k => (r[k] ??= []).push(o[k]));
        return r;
    }, {});

console.log(grouped);

CodePudding user response:

You can do something like this:

const dd = [
{
  keyone: "test",
  two: "you",
  three: 'op'
},
{
  keyone: "youuuu",
  two: "ttt",
  three: 'op'
},
{
  keyone: "operation",
  two: "test",
  three: 'op'
}];
const result = dd.reduce((prev, acc, arr ) => {
       if (acc['keyone']) { prev['keyone'].push(acc['keyone']) } 
       if (acc['two']) { prev['two'].push(acc['two']) }
       return prev;
}, {keyone: [], two: []});

console.log(result);

CodePudding user response:

You can do it by one iteration on your array using reduce and on every iteration, iterating over your object by Object.keys and forEach:

const data = [ { keyone: "test", two: "you", three: 'op' }, { keyone: "youuuu", two: "ttt", three: 'op' }, { keyone: "operation", two: "test", three: 'op' }];
const targetKeys = ['keyone', 'two']

const result = data.reduce((acc, obj)=> {
  targetKeys.forEach(k => { (acc[k] = acc[k] || []).push(obj[k]) });
  return acc;
}, {});

console.log(result);

CodePudding user response:

I think this is the answer you were looking for:
(using object destructuring to extract 'keyone' and 'two' from each object and push them within the same map loop)
Don't forget to check for undefined. My code here assumes you don't want zeros or empty strings.

const data = 
[{ keyone: "test", two: "you", three: 'op' }, { keyone: "youuuu", two: "ttt", three: 'op' }, { keyone: "operation", two: "test", three: 'op' }];

const test = { keyone:[], two:[] }
data.map(({ keyone, two }) => {
   if ( keyone )
      test.keyone.push( keyone );
   if ( two )
      test.two.push( two )
})

console.log( test )

CodePudding user response:

I'm fairly new to JavaScript and maybe my solution is not the best. I created a function, where you can add as an optional parameter the amount of keys you want to getter the information from. I asumed that you don't know the name of the keys.

const dd = [{
  keyone: "test",
  two: "you",
  three: 'op',
}, {
  keyone: "youuuu",
  two: "ttt",
  three: 'op',
}, {
  keyone: "operation",
  two: "test",
  three: 'op',
}];

getterInformation(dd);

function getterInformation(object, keyCount = Object.keys(object).length) {
  let objectWithDesiredKey = {};

  for (let index = 0; index < keyCount; index  ) {
    objectWithDesiredKey[`${Object.keys(object[0])[index]}`] = [];
  }

  object.forEach((items) => {
    for (const key in items) {
      if (key in objectWithDesiredKey) {
        objectWithDesiredKey[key].push(items[key]);
      }
    }
  });

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

CodePudding user response:

const dd = [{
        keyone: "test",
        two: "you",
        three: 'op'
    },
    {
        keyone: "youuuu",
        two: "ttt",
        three: 'op'
    },
    {
        keyone: "operation",
        two: "test",
        three: 'op'
    }
];

const pullOut = (...keys) => {
    return keys.map(key => {
        const val = dd.reduce((pV, cV, cI) => {
            pV.push(cV[key]);
            return pV;
        }, []);
        return {
            [key]: val
        };
    }).reduce(((r, c) => Object.assign(r, c)), {});
};

console.log(pullOut('keyone', 'two'));

CodePudding user response:

Here is a function that takes an array of objects, followed by any number of keys you wish to gather (I have used the rest parameter syntax to gather the list of keys.). This function loops once for the number of keys you want to collect, and once for the number of objects (O(m.n): the same as reduce). A third loop initialising the array could be combined with the object loop but I have left it there for readability. (so it is O(m.n m))
I don't see any need or advantage in using reduce, forEach or map is more readable.

function reduceArrayOfObjectsToArraysOfValues( 
                                 arrayOfObjects, 
                                 ...keys 
                                 ){
  const result = {}
  keys.forEach( key => {
    result[ key ] = []
  })
  arrayOfObjects.forEach( obj => {
    keys.forEach( key => {
      if ( obj.hasOwnProperty( key )) {
        result[key].push( obj[key] )
      }
    })
  })
  return result
}

const data = [ { keyone: "test", two: "you", three: 'op' }, { keyone: "youuuu", two: "ttt", three: 'op' }, { keyone: "operation", two: "test", three: 'op' }];


console.log( reduceArrayOfObjectsToArraysOfValues( data, 'keyone', 'two' ))

// == { "keyone": [ "test", "youuuu", "operation"],
//         "two": [ "you", "ttt", "test" ]}

  •  Tags:  
  • Related