3

I have a javascript array which get created dynamically in this format.

[{prdName: "Testing2"},
{prdName: "Testing2,Testing3"},
{markets: "Testing5"},
{markets: "Testing5,Testing6"}]

I want to remove the duplicate key in the above array map and convert it into this format.

 [ {prdName: "Testing2,Testing3"},
   {markets: "Testing5,Testing6"} ]

Could you let me know how to achieve the same. I am working on a reactjs application.

2
  • 1
    Does the filtering have to be aware of the values inside the strings? For example, if the array is [{a:"Test1"}, {a:"Test2"}] the result must be [{a:"Test1,Test2"}] or it's enough to just get the latest ocurrence of "a" (resulting in [{a:"Test2"}])? Commented Oct 27, 2017 at 18:57
  • Does the output really need to be an array? It looks like you could just merge all of the objects into one, and it would remove duplicate keys. Commented Oct 27, 2017 at 19:00

3 Answers 3

3

With ES6, you could use Map with Set for unique items.

var array = [{ prdName: "Testing2" }, { prdName: "Testing2,Testing3" }, { markets: "Testing5" }, { markets: "Testing5,Testing6" }],
    map = new Map,
    result;

array.forEach(o => Object.keys(o).forEach(k => {
    if (!map.has(k)) {
        map.set(k, new Set);
    }
    o[k].split(',').forEach(s => map.get(k).add(s));
}));

result = [...map].map(([k, s]) => ({ [k]: [...s].join() }));

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

Sign up to request clarification or add additional context in comments.

Comments

2

I'm assuming that you want to preserve all of the non-duplicate comma-delimited entries, not just throw away all but the last group as in the other answers. (So, for example, if the input were [{foo: "x"}, {foo:"x,y"}, {foo:"z"}] the output should be [{foo: "x,y,z"}], not [{foo:"z"}].)

var rearrange = function(input) {
  var tmp = {}; // track keys and values as we find them
  for (obj of input) {
    var key = Object.keys(obj)[0]; // each input has one key
    tmp[key] = tmp[key] || {}; // initialize an empty object at that key in tmp if necessary
    var vals = obj[key].split(",");
    for (v of vals) {
      tmp[key][v.trim()] = 1; // keep each of the (trimmed) comma-delimited values, implicitly dropping duplicates
    }
  }

  // now convert the tmp object into an array:
  var output = [];
  for (k of Object.keys(tmp)) {
    var x = {};
    x[k] = Object.keys(tmp[k]).join(","); // merge the values back into a comma-separated string
    output.push(x);
  }
  return output;
}
console.log(rearrange([
  {prdName: "Testing2"},
  {prdName: "Testing2,Testing3"},
  {markets: "Testing5"},
  {markets: "Testing5,Testing6"}
]));

console.log(rearrange([
  {foo: "x"},
  {foo: "x,y"},
  {foo: "z"},
  {bar: "x,y,z"}
]));

If, however, all you need is the last instance of each key, this is pretty close to a one-liner; just use Object.assign to merge the objects:

var rearrange = function(input) {
   var merged = Object.assign({},...input); // merges all input keys, overwriting early values with later ones
   
   // convert to array (if necessary. the "merged" object might be easier to work with...):
   var output=[];
   for (k of Object.keys(merged)) {
     var x = {};
     x[k] = merged[k];
     output.push(x)
   }
   return output;
}

console.log(rearrange([
    {prdName: "Testing2"},
    {prdName: "Testing2,Testing3"},
    {markets: "Testing5"},
    {markets: "Testing5,Testing6"}
]));
     
console.log(rearrange([{foo: "x"}, {foo:"x,y"}, {foo:"z"}]));

Comments

1

var lists =[{prdName: "Testing2"},

{prdName: "Testing2,Testing3"},

{markets: "Testing5"},

{markets: "Testing5,Testing6"}]

var newLists =[]
var keys = []
lists.forEach(item=>{
var key = Object.keys(item)[0];
if(keys.indexOf(key) === -1){
// first time the key is processed; it is stored in newLists
    keys.push(key);
    newLists.push(item);
  }
else {
// a duplicate key is found in the array
    let remove; 
    let values;
    newLists.forEach((item2,index) => {
        if (Object.keys(item2)[0] === key) {
// use of a set to have a union of values already stored for the key and the new values found for the same key using spread operator        
         values = new Set([...item2[key].split(","),...item[key].split(",")]);
            remove = index;
          }
    })
    newLists.splice(remove, 1);
    newLists.push({[key]:  Array.from(values).toString()})
  }
})

console.log(newLists);

6 Comments

Hi edkeveked, These values are formed dynamically. Skipping the first value wouldn't work in cases when there is only one single value. e.g. var lists =[{prdName: "Testing2"}, The above code will return empty array in this case.
Yes, definitely, it won't work. But actually, you did not specify that in the answer. You have to give a more general JSON.
Sorry. I mentioned it gets created dynamically. So we are not sure if it will be a single value. Thanks for the solution !
But you said "dynamically in this format"; I could modify my post or even delete it since there are others answers. But I guess, the question would have been easier to understand, if the JSON you gave were more general
That's pretty disingenuous, @edkeveked. This isn't far from console.log('correct output') and saying "well you didn't say it wouldn't always be the exact same input..."
|

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.