Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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.

like image 451
ni8mr Avatar asked Jun 27 '16 05:06

ni8mr


People also ask

How do you remove duplicate values from an array of objects?

To remove the duplicates from an array of objects: Use the Array. filter() method to filter the array of objects. Only include objects with unique IDs in the new array.

How do you get rid of repeating elements in an array?

1) Remove duplicates from an array using a Set To remove duplicates from an array: First, convert an array of duplicates to a Set . The new Set will implicitly remove duplicate elements. Then, convert the set back to an array.


5 Answers

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);
like image 181
Nina Scholz Avatar answered Oct 04 '22 13:10

Nina Scholz


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);
like image 33
Aditya Singh Avatar answered Sep 30 '22 13:09

Aditya Singh


//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)
like image 20
Dipak Prajapati Avatar answered Sep 30 '22 13:09

Dipak Prajapati


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

like image 37
brk Avatar answered Oct 03 '22 13:10

brk


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)
like image 23
Morteza Tourani Avatar answered Sep 30 '22 13:09

Morteza Tourani