Radoslav T.
Radoslav T.

Reputation: 75

Removing specific duplicates from object array in Underscore.js based on key values

I have an array like this:

var array = [
      {"id":"A","type":"blue","rng":"50"},
      {"id":"A","type":"blue","rng":"75"},
      {"id":"A","type":"grey","rng":"76"},

      {"id":"B","type":"blue","rng":"50"},
      {"id":"B","type":"grey","rng":"85"},
      {"id":"B","type":"grey","rng":"86"},

      {"id":"C","type":"blue","rng":"50"},
      {"id":"C","type":"grey","rng":"65"}
    ]

Note: Objects arranged in random order.

I need away to filter out the duplicate "id":"*","type":"blue" and "id":"*","type":"grey" with the higher "rng".

So the final result is:

var result = [
      {"id":"A","type":"blue","rng":"50"},
      {"id":"A","type":"grey","rng":"76"},

      {"id":"B","type":"blue","rng":"50"},
      {"id":"B","type":"grey","rng":"86"},

      {"id":"C","type":"blue","rng":"50"},
      {"id":"C","type":"grey","rng":"65"}
    ]

I'm keen on using underscore but any other solution is welcome too.

Upvotes: 0

Views: 77

Answers (2)

Nenad Vracar
Nenad Vracar

Reputation: 122087

You can use forEach() loop and one object as thisArg parameter to check if object with same id|type exists.

var array = [{"id":"A","type":"blue","rng":"50"},{"id":"A","type":"blue","rng":"75"},{"id":"A","type":"grey","rng":"76"},{"id":"B","type":"blue","rng":"50"},{"id":"B","type":"grey","rng":"85"},{"id":"B","type":"grey","rng":"86"},{"id":"C","type":"blue","rng":"50"},{"id":"C","type":"grey","rng":"65"}]
    
var result = []
array.forEach(function(e) {
  // Create key with id and type
  var key = e.id + '|' + e.type;
  // Check if key exists in this object and if it doesn't create property with value of current value and push that value to result array
  if(!this[key]) this[key] = e, result.push(this[key])
  else {
    // Otherwise check if rng of current element is < of rng of previous object with same key and if it is set rng to rng of current object
    if(e.rng < this[key].rng) this[key].rng = e.rng
  }
}, Object.create(null))
    
 console.log(result)

Upvotes: 1

Nina Scholz
Nina Scholz

Reputation: 386746

You could use a hash table and a combined key as reference to the index.

var data = [{ id: "A", type: "blue", rng: "50" }, { id: "A", type: "blue", rng: "75" }, { id: "A", type: "grey", rng: "76" }, { id: "B", type: "blue", rng: "50" }, { id: "B", type: "grey", rng: "85" }, { id: "B", type: "grey", rng: "86" }, { id: "C", type: "blue", rng: "50" }, { id: "C", type: "grey", rng: "65" }],
    result = data.reduce(function (hash) {
        return function (r, o) {
            var key = ['id', 'type'].map(function (k) { return o[k]; }).join('|');
            if (!(key in hash)) {
                hash[key] = r.push(o) - 1;
            } else if (r[hash[key]].rng < o.rng) {
                r[hash[key]] = o;
            }
            return r;
        };
    }(Object.create(null)), []);

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

Upvotes: 2

Related Questions