giiyiraj
giiyiraj

Reputation: 73

Group objects based on similar value in array of objects

I have an array of objects I want to group/merge the objects which have similar branches and environments and concat their pools at the same time.

const data = [
  {
    branch: "master",
    environment: "dev",
    pool: "6g",
    service: "amex",
  },
  {
    branch: "master",
    environment: "dev",
    pool: "6g",
    service: "amex",
  },
  {
    branch: "feature/rest",
    environment: "dev",
    pool: "2g",
    service: "amex",
  },
  {
    branch: "master",
    environment: "dev",
    pool: "4g",
    service: "amex",
  },
  {
    branch: "hotfix/23",
    environment: "test",
    pool: "9g",
    service: "amex",
  },
  {
    branch: "hotfix/23",
    environment: "test",
    pool: "1g",
    service: "amex",
  },
];

I want the result in the below format removing duplicate objects as well I tried to reduce it but as array reduce returns a single object as a result and the other objects are being omitted from the response what data structure or way I can use to achieve the result?

const result = [
  {
    branch: "master",
    environment: "dev",
    pool: "6g, 4g",
    service: "amex",
  },
  {
    branch: "feature/rest",
    environment: "dev",
    pool: "2g",
    service: "amex",
  },
  {
    branch: "hotfix/23",
    environment: "test",
    pool: "9g,1g",
    service: "amex",
  },
];

Upvotes: 1

Views: 111

Answers (5)

AMunim
AMunim

Reputation: 1161

Just create a dictionary out of them and fill in the values.

const data=[{branch:"master",environment:"dev",pool:"6g",service:"amex"},{branch:"feature/rest",environment:"dev",pool:"2g",service:"amex"},{branch:"master",environment:"dev",pool:"4g",service:"amex"},{branch:"hotfix/23",environment:"test",pool:"9g",service:"amex"},{branch:"hotfix/23",environment:"test",pool:"1g",service:"amex"},]


let x = {};
data.forEach(y => x[y.branch + "|" + y.environment] = y);

var res = Object.values(x).map(y => Object.assign({}, y)).map(y => 
{
    y.pool = data.filter(d => d.branch == y.branch && d.environment == y.environment).map(x => x.pool).join(",");
   return y;
})

If you do not care about immutability(original objects in data change), then remove Object.assign map and it will yield the same results

Upvotes: 2

Albi Patozi
Albi Patozi

Reputation: 1468

const data = [{
    branch: "master",
    environment: "dev",
    pool: "6g",
    service: "amex",
  },
  {
    branch: "feature/rest",
    environment: "dev",
    pool: "2g",
    service: "amex",
  },
  {
    branch: "master",
    environment: "dev",
    pool: "4g",
    service: "amex",
  },
  {
    branch: "hotfix/23",
    environment: "test",
    pool: "9g",
    service: "amex",
  },
  {
    branch: "hotfix/23",
    environment: "test",
    pool: "1g",
    service: "amex",
  },
];

var cacheMix = {};

for (var i = 0; i < data.length; i++) {

  var item = data[i];
  var compositeKey = item.environment + "~" + item.branch;

  if (cacheMix[compositeKey]) {
    cacheMix[compositeKey].pools[item.pool] = 1;
  } else {
    var pools = {}; pools[item.pool] = 1; //to avoid dublicate pools 
    cacheMix[compositeKey] = {
      branch: item.branch,
      environment: item.environment,
      service: item.service,
      pools: pools 
    }
  }
}


var result = [];


for (var key in cacheMix) {

  var item = cacheMix[key];
  result.push({
    branch: item.branch,
    environment: item.environment,
    service: item.service,
    pool: Object.keys(item.pools).join(", ")
  });
}

console.log(result);

Upvotes: 5

pbialy
pbialy

Reputation: 1083

data.reduce((prev, curr) => {
  const container = prev.find(
    el => (el.branch === curr.branch) && (el.environment === curr.environment)
  );
  if (container) {
    container.pool = container.pool + `,${curr.pool}`
    return prev;
  } else {
    return prev.concat({...curr}) 
  }
}, [])

but I would suggest to instead create an object with keys equal to branch names.

Upvotes: 0

symlink
symlink

Reputation: 12209

This is one way to do it:

const data=[{branch:"master",environment:"dev",pool:"6g",service:"amex"},{branch:"feature/rest",environment:"dev",pool:"2g",service:"amex"},{branch:"master",environment:"dev",pool:"4g",service:"amex"},{branch:"hotfix/23",environment:"test",pool:"9g",service:"amex"},{branch:"hotfix/23",environment:"test",pool:"1g",service:"amex"},]

const res = data.reduce((acc, cur) =>
{
    let isMatch = false
    acc.forEach((el, idx) => {
        if(el.branch === cur.branch && el.environment === cur.environment) {
            if(acc[idx].service !== cur.service) {
                acc[idx].service += `, ${cur.service}`
            }
            if(acc[idx].pool !== cur.pool) {
                acc[idx].pool += `, ${cur.pool}`
            }
            isMatch = true
        }
    })
    if(!isMatch) {
        acc.push(cur)    
    }
    
    return acc
}, [])

console.log(res)

Upvotes: 0

Terry Lennox
Terry Lennox

Reputation: 30685

I'd suggest using Array.reduce() for this, creating a map of the data using a key created from the branch and environment.

Once we have the map object, we can use Object.values() to return an array of the desired results.

const data = [ { branch: "master", environment: "dev", pool: "6g", service: "amex", }, { branch: "feature/rest", environment: "dev", pool: "2g", service: "amex", }, { branch: "master", environment: "dev", pool: "4g", service: "amex", }, { branch: "hotfix/23", environment: "test", pool: "9g", service: "amex", }, { branch: "hotfix/23", environment: "test", pool: "1g", service: "amex", }, ];

const result = Object.values(data.reduce((acc, { branch, environment, pool, service }) => {
    // Our grouping key...
    const key = `${branch}-${environment}`;
    acc[key] = acc[key] || { branch, environment, pool: '', service };
    acc[key].pool += ((acc[key].pool ? ", " : "" ) + pool);
    return acc;
}, {}))

console.log('Result:', result)
.as-console-wrapper { max-height: 100% !important; }

Upvotes: 0

Related Questions