简体   繁体   中英

combine objects in an array and push to an array in the object

  • In the end there should be only one object per name .
  • If there are multiple objects with the same name make it so that the number array for each object get combined into the one object for that name
  • The one object with the same name should not have duplicate elements in the number array.
  • The elements in the number array should appear in the same order as they appear in the original array.

     var arrT = [ {name : "x.com", number :["123-456-789"]}, {name : "x.com", number :["452-123-789"]},{name : "y.com", number :["123-456-000"]}, {name : "x.com", number :["123-456-789"]}, {name : "y.com", number :["123-456-000"]}, {name : "b.com", number :["178-456-000"]} ] output should be:[ {name : "x.com", number : ["123-456-789", "452-123-789"]}, //notice: 123-456-789 didn't appear twice {name : "y.com", number : ["123-456-000"]}, {name : "b.com", number :["178-456-000"]} ] 

I was able to find out how many times an object with the same name occurred

var occurrences = nArr.reduce(function(acc, curr,i){
    if(typeof acc[curr.name] == "undefined"){
        acc[curr.name] = 1;
    }else{
        acc[curr.name] += 1
    }
    return acc;
}, {});
console.log(occurrences)

var moreThanOne = [];
for(var key in occurrences){
    if(occurrences[key] > 1){
        moreThanOne.push(key);
    }
}
console.log("moreThanOne", moreThanOne)

but then it got complicated because I didn't know how to remove the duplicates and leave one and combine the number array

Not sure if you have some constraints but that's how I'd do it.

Loop over all of your object and put them into an object. The key of the object will be the name. Check if the object exists, if it doesn't add it and replace the number by [number] , if the object already exists, simply add the number with push .

Once you looped over all your objects, convert that object to a list and that's it.

function groupByName(accum, obj) {
  if (accum[obj.name]) {
    // add all numbers! don't check for uniqueness yet
    accum[obj.name].number = accum[obj.name].concat(obj.number)
  } else {
    accum[obj.name] = obj
    obj.number = [obj.number]
  }
  return accum
}

function removeDuplicates(accum, value) {
  if (accum.length == 0 && accum[accum.length - 1] != value) {
    accum.push(value)
  }
  return accum
}

function toList(context) {
  return function (key) {
    var obj = context[key]
    obj.number.sort()
    obj.number = obj.number.reduce(removeDuplicates, [])
    return obj
  }
}

objs = arrT.reduce(groupByName, {})
output = Object.keys(objs).map(toList(objs))

Note that I'm ediding the first object so if there is no use for those objects anywhere else, that's fine... if not, you should copy in the reduce function instead of modifying and existing object.

If you only want to keep the unique numbers you just have to check if the numbers are already in.

This example creates a new object first, checks if the the name exists already, when it doesn't exist, it adds it as a completely new reference (including the number array, so your original source remains the same) and if it does exist, it will loop through the number array to see which ones should be added still.

 var arrT = [{ name: "x.com", number: ["123-456-789"] }, { name: "x.com", number: ["452-123-789"] }, { name: "y.com", number: ["123-456-000"] }, { name: "x.com", number: ["123-456-789"] }, { name: "y.com", number: ["123-456-000"] }, { name: "b.com", number: ["178-456-000"] }]; var reduced = arrT.reduce((nextState, item) => { var key = item.name, o; if (!(o = nextState[key])) { // clones the item, and the number array nextState[key] = { ...item, number: [...item.number] }; } else { item.number.forEach(number => o.number.indexOf(number) === -1 && o.number.push(number)); } return nextState; }, {}); console.log(arrT); console.log(Object.keys(reduced).map(key => reduced[key])); 

Another (ES6) version for the mix: with a Map and Sets

 let arrT = [{name : "x.com", number :["123-456-789"]}, {name : "x.com", number :["452-123-789"]},{name : "y.com", number :["123-456-000"]}, {name : "x.com", number :["123-456-789"]}, {name : "y.com", number :["123-456-000"]}, {name : "b.com", number :["178-456-000"]} ]; let res = [...arrT.reduce((m,o) => { let set = m.get(o.name); if(!set) m.set(o.name, set = new Set()); for(let n of o.number) set.add(n); return m; }, new Map())] .map(([na,[...nrs]])=>({name:na,number:nrs})); console.log(res); 

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM