ni8mr
ni8mr

Reputation: 1785

Removing elements from an array of objects based on duplicate values of multiple keys

I have an array of objects like this -

var arr = [
    { type_id: "3", full_empty:"true", quantity:1},
    { type_id: "3", full_empty:"true", quantity:1},
    { type_id: "9", full_empty:"true", quantity:4},
    { type_id: "9", full_empty:"false", quantity:4},
    { type_id: "9", full_empty:"true", quantity:4},
    { type_id: "9", full_empty:"true", quantity:4},
    { type_id: "9", full_empty:"true", quantity:4}
];

I want to remove the duplicates having same type_id and full_empty values. The result should look like this -

var arr = [
    { type_id: "3", full_empty:"true", quantity:1},
    { type_id: "9", full_empty:"true", quantity:4},
    { type_id: "9", full_empty:"false", quantity:4},
];

I have searched and found some solution, but some of them are for removing duplicate keys or for removing duplicates based on duplicate value of only one key. Some required external libraries. Also there are some solutions which i can't understand. Is there any easy way to do this in plain JavaScript ?

Edit for better understand - I have read this question . Accepted answer on that question is for finding duplication for only one key. In my case, I have to find the duplication for multiple keys.

Upvotes: 9

Views: 5438

Answers (9)

aryan malik
aryan malik

Reputation: 31

var arr = [
    { type_id: "3", full_empty:"true", quantity:1},
    { type_id: "3", full_empty:"true", quantity:1},
    { type_id: "9", full_empty:"true", quantity:4},
    { type_id: "9", full_empty:"false", quantity:4},
    { type_id: "9", full_empty:"true", quantity:4},
    { type_id: "9", full_empty:"true", quantity:4},
    { type_id: "9", full_empty:"true", quantity:4}
];

let op = [];

arr.forEach((el) => {
  if (isNotExist(el)){
    op.push(el)
  }
  function isNotExist(obj){
    return op.every(el => JSON.stringify(el) !== JSON.stringify(obj) )
  	
  }
})

console.log(op)

Upvotes: 0

Jeex
Jeex

Reputation: 306

This is my modified version of Aditya Singh's answer

var arr = [
                { type_id: "3", full_empty:"true", quantity:1},
                { type_id: "3", full_empty:"true", quantity:1},
                { type_id: "9", full_empty:"true", quantity:4},
                { type_id: "9", full_empty:"false", quantity:4},
                { type_id: "9", full_empty:"true", quantity:4},
                { type_id: "9", full_empty:"true", quantity:4},
                { type_id: "9", full_empty:"true", quantity:4}
            ];


    var a = arr.reduce((accumulator, current) => {

     const isAlreadyExist = accumulator.some(item => (
      item.type_id === currentVal.type_id && item.full_empty === currentVal.full_empty
     ))

     return isAlreadyExist(current) ? accumulator : [...accumulator, current];
    }, []);

    console.log(a);

Upvotes: 0

Morteza Tourani
Morteza Tourani

Reputation: 3536

This not as awesome as Ninas answer but can be noticed and a new answer.

var arr = [ { type_id: "3", full_empty: "true", quantity: 1 }, { type_id: "3", full_empty: "true", quantity: 1 }, { type_id: "9", full_empty: "true", quantity: 4 }, { type_id: "9", full_empty: "false", quantity: 4}, { type_id: "9", full_empty: "true", quantity: 4 }, { type_id: "9", full_empty: "true", quantity: 4 }, { type_id: "9", full_empty: "true", quantity: 4}];

var dict = {}, result = [];

arr.forEach((i, key) => {
  !dict[(key = i.type_id + i.full_empty)] 
      && (dict[key] = result.push(i));
})
console.log(result)

Upvotes: 1

Nina Scholz
Nina Scholz

Reputation: 386756

Despite the other solutions, I suggest to use a hash table with type_id and full_empty as key and if a new found then set hash to true. Together with Array#filter, you get a new array with the unique items.

var arr = [{ type_id: "3", full_empty: "true", quantity: 1 }, { type_id: "3", full_empty: "true", quantity: 1 }, { type_id: "9", full_empty: "true", quantity: 4 }, { type_id: "9", full_empty: "false", quantity: 4 }, { type_id: "9", full_empty: "true", quantity: 4 }, { type_id: "9", full_empty: "true", quantity: 4 }, { type_id: "9", full_empty: "true", quantity: 4 }],
    filtered = arr.filter(function (a) {
        var key = a.type_id + '|' + a.full_empty;
        if (!this[key]) {
            this[key] = true;
            return true;
        }
    }, Object.create(null));

console.log(filtered);

ES6

var arr = [{ type_id: "3", full_empty: "true", quantity: 1 }, { type_id: "3", full_empty: "true", quantity: 1 }, { type_id: "9", full_empty: "true", quantity: 4 }, { type_id: "9", full_empty: "false", quantity: 4 }, { type_id: "9", full_empty: "true", quantity: 4 }, { type_id: "9", full_empty: "true", quantity: 4 }, { type_id: "9", full_empty: "true", quantity: 4 }],
    filtered = arr.filter(
        (temp => a =>
            (k => !temp[k] && (temp[k] = true))(a.type_id + '|' + a.full_empty)
        )(Object.create(null))
    );

console.log(filtered);

Upvotes: 5

Aditya Singh
Aditya Singh

Reputation: 16690

You can use pure functions by using Array.some() and Array.reduce() to reduce your input array to array of distinct elements as shown below

    var arr = [
        { type_id: "3", full_empty:"true", quantity:1},
        { type_id: "3", full_empty:"true", quantity:1},
        { type_id: "9", full_empty:"true", quantity:4},
        { type_id: "9", full_empty:"false", quantity:4},
        { type_id: "9", full_empty:"true", quantity:4},
        { type_id: "9", full_empty:"true", quantity:4},
        { type_id: "9", full_empty:"true", quantity:4}
    ];

    var a = arr.reduce(function (accumulator, current) {
      if (checkIfAlreadyExist(current)) {
        return accumulator
      } else {
        return accumulator.concat([current]);
      }
      
      function checkIfAlreadyExist(currentVal) {
        return accumulator.some(function(item){
          return (item.type_id === currentVal.type_id &&
                  item.full_empty === currentVal.full_empty);
        });
      }
    }, []);
        
    console.log(a);

Concise ES6 syntax

A more concise reduce can be written using ES6 arrow functions and spread operator as below:

var arr = [
            { type_id: "3", full_empty:"true", quantity:1},
            { type_id: "3", full_empty:"true", quantity:1},
            { type_id: "9", full_empty:"true", quantity:4},
            { type_id: "9", full_empty:"false", quantity:4},
            { type_id: "9", full_empty:"true", quantity:4},
            { type_id: "9", full_empty:"true", quantity:4},
            { type_id: "9", full_empty:"true", quantity:4}
        ];

var a = arr.reduce((accumulator, current) => {
  if (checkIfAlreadyExist(current)) {
    return accumulator;
  } else {
    return [...accumulator, current];
  }

  function checkIfAlreadyExist(currentVal) {
    return accumulator.some((item) => {
      return (item.type_id === currentVal.type_id &&
              item.full_empty === currentVal.full_empty);
    });
  }
}, []);
            
console.log(a);

Upvotes: 13

brk
brk

Reputation: 50336

You can use find and forEach to create a new array from this array which contain duplicate values

Hope this snippet will be useful

var arr = ["Json Array object as supplied in the question"];

// A new array which will contain unique json object
var newArray = [];

//Loop through each of the object in the original array

arr.forEach(function(item) {
    // If newArray .length is zero then just push the first element
    // else in newArray find if a json object already exist which have same
    // type_id & full_empty. If it does not exist it will return undefined
    if (newArray.length !== 0) {
        var _isPresent = newArray.find(function(secItem) {
            return secItem.type_id === item.type_id && secItem.full_empty === item.full_empty
        })
        // If element is not present then push this json pbject
        if (_isPresent == undefined) {
            newArray.push(item)
        }
    } else {  // this will execute only once when newArray length is 0

        newArray.push(item)
    }
})
console.log(newArray)

JSFIDDLE

Upvotes: 1

Dipak Prajapati
Dipak Prajapati

Reputation: 528

//To search the element is already exisit or not.(to remove Duplicate)
    function searchExisting(type_id,full_empty,newArray){
        for(var i=0;i<newArray.length;i++){
            if(newArray[i].type_id==type_id && newArray[i].full_empty==full_empty){
                return true;
            }
        }
        return false;
    }

//loop through every element and push it into new array
    var arr2=[];
    for(var i=0;i<arr.length;i++){
        if(!searchExisting(arr[i].type_id,arr[i].full_empty,arr2)){
            arr2.push(arr[i]);
        }
    }
    console.log(arr2)

Upvotes: 1

Anand Deep Singh
Anand Deep Singh

Reputation: 2620

If you don't want to get into code so you can use below snippet :-

var sDat = [
{ sid:12, scode:"code", sname:"Deep" },
{ sid:12, scode:"code", sname:"Anand" },
{ sid:139, scode:"code", sname:"Singh"}
];

function cleanup(arr, prop) {
var new_arr = [];
var lookup  = {};

for (var i in arr) {
    lookup[arr[i][prop]] = arr[i];
}

for (i in lookup) {
    new_arr.push(lookup[i]);
}

return new_arr;
}

var n = cleanup(sDat, 'sid');
alert(n);

I hope this will work for you.

Upvotes: 0

andre mcgruder
andre mcgruder

Reputation: 1520

The array object has filter and map on it. You can use filter to target the properties of the inactive that you want. It a boolean evaluation that returns a "filtered" new array.

Here is a great video tutorial posted on the Egghead.IO site that really breaks it down.

Upvotes: 0

Related Questions