How to merge objects if certain keys and values ma

2020-04-20 07:11发布

问题:

I want to merge the last keys that can be any random string of all the objects in the array if the fname and address is same. To give more context, I need this format to draw a graph with recharts.

const data = [
  {
    fname: "adam",
    address: "us",
    key1: 12
  },
  {
    fname: "adam",
    address: "us",
    key2: 31
  },
  {
    fname: "adam",
    address: "uk",
    qwe: 41
  },
  {
    fname: "Dan",
    address: "au",
    asd: 31
  },
  {
    fname: "Dan",
    address: "au",
    zxc: 31
  },
  {
    fname: "Chris",
    address: "nz",
    randomkey: 12 
  },
  {
    fname: "Chris",
    address: "br",
    randomkey2: 14 
  },
];

This should return something like

const data = [
  {
    fname: "adam",
    address: "us",
    key1: 12,
    key2: 31
  },
  {
    fname: "adam",
    address: "uk",
    qwe: 41
  },
  {
    fname: "Dan",
    address: "au",
    asd: 31,
    zxc: 31
  },
  {
    fname: "Chris",
    address: "nz",
    randomkey: 12 
  },
  {
    fname: "Chris",
    address: "br",
    randomkey2: 14 
  },
];

回答1:

Using a very naive approach, you could create a hash map to collect the unique name + address, then iterate over the map. Something like this:

const data = [{}, {}, {}] //...data in question
var map = {};
data.forEach(function(item) {
  var id = item.fname + "|" + item.address; // | cannot occur in address or name
  if (map[id] === undefined) {
    map[id] = item;
  } else {
    var existing = map[id]; // adding/updating new keys
    for (var propt in item) {
      existing[propt] = item[propt];
    }
  }
});
var results = [];
Object.keys(map).forEach(k => results.push(map[k]));

Then results should hold your processed data



回答2:

const data = [
  {
    fname: "adam",
    address: "us",
    key1: 12
  },
  {
    fname: "adam",
    address: "us",
    key2: 31
  },
  {
    fname: "adam",
    address: "uk",
    qwe: 41
  },
  {
    fname: "Dan",
    address: "au",
    asd: 31
  },
  {
    fname: "Dan",
    address: "au",
    zxc: 31
  },
  {
    fname: "Chris",
    address: "nz",
    randomkey: 12 
  },
  {
    fname: "Chris",
    address: "br",
    randomkey2: 14 
  },
]
const result=[]
data.forEach((obj,index)=>{
    let found=false;
	index===0?result.push(obj):result.forEach((obj2,index2)=>{
		if(obj2.fname===obj.fname&&obj2.address===obj.address){
    		result[index2]={...obj,...obj2}
            found=true;
            }
       })
       found===false&&index!==0&&result.push(obj)
})
console.log(result)

I know it's already been answered but I found it interesting to solver



回答3:

You could take an object with some properties from data as keys for collecting the objects.

const
    data = [{ fname: "adam", address: "us", key1: 12 }, { fname: "adam", address: "us", key2: 31 }, { fname: "adam", address: "uk", qwe: 41 }, { fname: "Dan", address: "au", asd: 31 }, { fname: "Dan", address: "au", zxc: 31 }, { fname: "Chris", address: "nz", randomkey: 12  }, { fname: "Chris", address: "br", randomkey2: 14 }],
    keys = ['fname', 'address'],
    result = Object.values(data.reduce((r, o) => {
        var key = keys.map(k => o[k]).join();
        Object.assign(r[key] =  r[key] || {}, o);
        return r;
    }, {}));

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



回答4:

The code is kind of complex. But it works fine.

/* DATA */
const data=[{fname:"adam",address:"us",key1:12},{fname:"adam",address:"us",key2:31},{fname:"adam",address:"uk",qwe:41},{fname:"Dan",address:"au",asd:31},{fname:"Dan",address:"au",zxc:31},{fname:"Chris",address:"nz",randomkey:12},{fname:"Chris",address:"br",randomkey2:14}];

/* ATTEMPT TO GET THE RESULT */
var temp = {};
for(var k in data){

  // finding the random key and random value
  var randkey, randvalue;
  for(var rk in data[k]){
    if(rk != 'fname' && rk != 'address'){
      randkey = rk;
      randvalue = data[k][rk];
    }
  }

  // getting fname and address
  var fname = data[k].fname;
  var address = data[k].address;

  // adding this data into the 'temp' object with the fname|address (if not exists already)
  // if exists then add the key only
  var unify = fname + '|' + address;
  if( !temp[unify] ){
    temp[unify] = {};
    temp[unify].fname = fname;
    temp[unify].address = address;
    temp[unify][randkey] = randvalue;
  }else{
    temp[unify][randkey] = randvalue;
  }

}


// getting the result array from temp
var result = [];
for(var k in temp ){
  result.push(temp[k]);
}

document.write( '<pre>' + JSON.stringify(result,0,3) + '</pre>' );