alyx alyx - 3 months ago 6
Javascript Question

Javascript: Find object array value dupes matching multiple fields

Given this object array:

[ { source_q_id: 'Q2B', target_q_id: null },
{ source_q_id: 'Q2B', target_q_id: null },
{ source_q_id: 'Q2B', target_q_id: null },
{ source_q_id: 'Q5C', target_q_id: 'Q7' },
{ source_q_id: 'Q5C', target_q_id: 'Q7' },
{ source_q_id: 'Q5C', target_q_id: 'Q7' },
{ source_q_id: 'Q5D', target_q_id: 'Q7' },
{ source_q_id: 'Q5D', target_q_id: 'Q7' },
{ source_q_id: 'Q5D', target_q_id: 'Q7' },
{ source_q_id: 'Q6A1', target_q_id: 'Q7' },
{ source_q_id: 'Q6A1', target_q_id: 'Q7' },
{ source_q_id: 'Q6A1', target_q_id: 'Q7' },
{ source_q_id: 'Q6A2', target_q_id: null },
{ source_q_id: 'Q6A2', target_q_id: null },
{ source_q_id: 'Q6A3', target_q_id: 'Q7' },
{ source_q_id: 'Q6A3', target_q_id: 'Q7' },
{ source_q_id: 'Q6A3', target_q_id: 'Q7' },
{ source_q_id: 'Q6B', target_q_id: 'Q6A2' },
{ source_q_id: 'Q6B', target_q_id: 'Q6A2' },
{ source_q_id: 'Q7', target_q_id: null },
{ source_q_id: 'Q7', target_q_id: null }]


I need a new array of unique dupes for both key/values:

[ { source_q_id: 'Q2B', target_q_id: null },
{ source_q_id: 'Q5C', target_q_id: 'Q7' },
{ source_q_id: 'Q5D', target_q_id: 'Q7' },
{ source_q_id: 'Q6A1', target_q_id: 'Q7' },
{ source_q_id: 'Q6A2', target_q_id: null },
{ source_q_id: 'Q6A3', target_q_id: 'Q7' },
{ source_q_id: 'Q6B', target_q_id: 'Q6A2' },
{ source_q_id: 'Q7', target_q_id: null }]


I'm using code from this SO answer, but it's removing too many
target_q_id
unique dupes as it isn't counting
source_q_id
dupes:

[ { source_q_id: 'Q2B', target_q_id: null },
{ source_q_id: 'Q5C', target_q_id: 'Q7' },
{ source_q_id: 'Q6B', target_q_id: 'Q6A2' } ]


The code:

function dupesOnly(arr, 'target_q_id') {
var seen = {},
ret = [];

arr.forEach(function(item) {
var key = item[field],
val = seen[key];

if (!val) {
seen[key] = val = {
initial: item,
count: 0
}
}

if (val.count === 1) {
ret.push(val.initial);
}
++val.count;
});

return ret;
}


How would I modify the code to find unique dupes for both
source_q_id
and
target_q_id
?

Answer

You can simply combine these properties and use as a key in your set.
Another note: if you .push items in .forEach, then you most probably do something wrong.

Try utilizing Array.prototype.filter:

Array.prototype.uniqueBy = function(keyBuilder) {
    var seen = {};
    return this.filter(function(o) {
      // build a filter key using a provided function
      var key = keyBuilder(o); 

      // if item already exists - do not add to the result
      if (seen[key]) 
        return false;
      
      // add item to the set and add item to the result
      // shortand for: 
      // seen[key] = true; return true;
      return (seen[key] = true);
    });
}

var obj = [{source_q_id:'Q2B',target_q_id:null},{source_q_id:'Q2B',target_q_id:null},{source_q_id:'Q2B',target_q_id:null},{source_q_id:'Q5C',target_q_id:'Q7'},{source_q_id:'Q5C',target_q_id:'Q7'},{source_q_id:'Q5C',target_q_id:'Q7'},{source_q_id:'Q5D',target_q_id:'Q7'},{source_q_id:'Q5D',target_q_id:'Q7'},{source_q_id:'Q5D',target_q_id:'Q7'},{source_q_id:'Q6A1',target_q_id:'Q7'},{source_q_id:'Q6A1',target_q_id:'Q7'},{source_q_id:'Q6A1',target_q_id:'Q7'},{source_q_id:'Q6A2',target_q_id:null},{source_q_id:'Q6A2',target_q_id:null},{source_q_id:'Q6A3',target_q_id:'Q7'},{source_q_id:'Q6A3',target_q_id:'Q7'},{source_q_id:'Q6A3',target_q_id:'Q7'},{source_q_id:'Q6B',target_q_id:'Q6A2'},{source_q_id:'Q6B',target_q_id:'Q6A2'},{source_q_id:'Q7',target_q_id:null},{source_q_id:'Q7',target_q_id:null}];
var objFiltered = obj.uniqueBy(function(o) { 
    return o.source_q_id + "~~~" + o.target_q_id;
});
console.log(objFiltered);

Comments