VonAxt
VonAxt

Reputation: 95

How to chunk an object into smaller objects

The goal is to break an object of unknown length and shape into small objects 3 elements each. Only vanilla JS solution; I don't want to use _.pick etc.

Example of large object:

const data = {
    someFirstKey: 'someFirstVal',
    someSecondKey: 'someSecondVal',
    ...
    someLastKey: 'someLastVal'
}

Desired chunk with 3 keys:

{someKey0: 'someVal0', someKey1: 'someVal1', someKey2, 'someVal2'}

Upvotes: 2

Views: 2760

Answers (5)

Enlico
Enlico

Reputation: 28500

For the readers who would come here not necessarily in search of vanilla solution, but who would be happy with more expressive (even if slower) solutions, such a solution with Lodash would be

_.map(_.chunk(_.toPairs(obj), 3), _.fromPairs)

// input
obj = { k1: 'v1', k2: 'v2', k3: 'v3', k4: 'v4', k5: 'v5', k6: 'v6', k7: 'v7', k8: 'v8' };

// magic
res = _.map(_.chunk(_.toPairs(obj), 3), _.fromPairs)

// print
console.log(res)
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.21/lodash.min.js" integrity="sha512-WFN04846sdKMIP5LKNphMaWzU7YpMyCU245etK3g/2ARYbPK9Ub18eG+ljU96qKRCWh+quCY7yefSmlkQw1ANQ==" crossorigin="anonymous" referrerpolicy="no-referrer"></script>

Upvotes: 1

Chirag B
Chirag B

Reputation: 2126

Using Object destructuring

const { someKey0, someKey1, someKey2 } = data

const newData = {
    someKey0,
    someKey1,
    someKey2
}

Upvotes: 0

Ben
Ben

Reputation: 3674

Using Object.fromEntries:

const entries = Object.entries(data);
const grouped = [];

for (let i = 0; i < entries.length; i++) {
    if (i % groupSize === 0) {
        grouped.push([entries[i]]);
    } else {
        grouped[Math.floor(i / groupSize)].push(entries[i]);
    }
}

const chunks = grouped.map(o => Object.fromEntries(o));

Upvotes: 1

Paul
Paul

Reputation: 141907

Based on the comments, it seems like you are actually looking for a way to split an object up into several smaller objects. I would approach that like this:

const data = {a:1,b:2,c:3,d:4,e:5,f:6,g:7};

const chunk_size = 3, chunks = [];
for ( const cols = Object.entries( data ); cols.length; )
  chunks.push( cols.splice(0, chunk_size).reduce( (o,[k,v])=>(o[k]=v,o), {}));

console.log( chunks );

Upvotes: 9

Paul
Paul

Reputation: 36349

Ok, so this might not be the most efficient way, but it works on my box. ;)

const data = {} // fill in your data here
const keys = Object.keys(data); // gets you the keys from your obj. 
const numberOfWholeParts = Math.floor( keys.length / 3 );  // or whatever your size limit is
const remainder = keys.length % 2; // keys left after all whole parts are filled

const arrayOfParts = [];

for(let i=0;i<numberOfWholeParts;i++) {
   const obj = {};
   const keySegment = keys.slice(i*3, i*3+3);

   for(let j=0; j<3; j++) {
     obj[keySegment[j]] = data[keySegment[j]];
   }
   arrayOfParts.push(obj);
} 
if(remainder > 0){
  const obj = {};
  let remainingKeys = keys.slice(-remainder)
  for(let i=0; i<remainingKeys.length;i++) {
    obj[remainingKeys[i]] = data[remainingKeys[i]];
  }
  arrayOfParts.push(obj);
}

Upvotes: 1

Related Questions