最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

Javascript - Return only unique values in an array of objects - Stack Overflow

programmeradmin2浏览0评论

I have an array of objects where I want to return only the unique objects based on their object Id.

I've tried to loop in the existing array data then find if the element was already add to a newly created array arr which should contain only the unique values, but it didn't work with me and I believe that I am missing something here or there.

Here is the current array :

          [
        {
          "objectId": "WMtwbyhFI6",
          "cuisineNameEn": "Cafe",
          "ordersNo": 20,
          "hidden": false
        },
        {
          "objectId": "QJSNTMpq5F",
          "ordersNo": 24,
          "cuisineNameEn": "Italian",
          "hidden": false
        },
        {
          "objectId": "iLXKswFRGa",
          "ordersNo": 5,
          "cuisineNameEn": "Japanese",
          "hidden": true
        },
        {
          "objectId": "Db0MeihpJE",
          "ordersNo": 6,
          "cuisineNameEn": "Fast Food",
          "hidden": false
        },
        {
          "objectId": "QJSNTMpq5F",
          "ordersNo": 24,
          "cuisineNameEn": "Italian",
          "hidden": false
        },
        {
          "objectId": "Db0MeihpJE",
          "ordersNo": 6,
          "cuisineNameEn": "Fast Food",
          "hidden": false
        },
        {
          "objectId": "Db0MeihpJE",
          "ordersNo": 6,
          "cuisineNameEn": "Fast Food",
          "hidden": false,
        },
        {
          "objectId": "Db0MeihpJE",
          "ordersNo": 6,
          "cuisineNameEn": "Fast Food",
          "hidden": false
        },
         {
          "objectId": "Db0MeihpJE",
          "ordersNo": 6,
          "cuisineNameEn": "Fast Food",
          "hidden": false
        },
         {
          "objectId": "Db0MeihpJE",
          "ordersNo": 6,
          "cuisineNameEn": "Fast Food",
          "hidden": false
        },
        {
          "objectId": "Db0MeihpJE",
          "ordersNo": 6,
          "cuisineNameEn": "Fast Food",
          "hidden": false
        }
      ]

However, this is what I want to return :

 [
        {
          "objectId": "WMtwbyhFI6",
          "cuisineNameEn": "Cafe",
          "ordersNo": 20,
          "hidden": false
        },
        {
          "objectId": "iLXKswFRGa",
          "ordersNo": 5,
          "cuisineNameEn": "Japanese",
          "hidden": true
        },
        {
          "objectId": "Db0MeihpJE",
          "ordersNo": 6,
          "cuisineNameEn": "Fast Food",
          "hidden": false
        },
        {
          "objectId": "QJSNTMpq5F",
          "ordersNo": 24,
          "cuisineNameEn": "Italian",
          "hidden": false
        }
      ]

I've tried the following:

 var arr = [];
  data.forEach((el)=>{
  if (arr.indexOf(el.objectId) === -1) {
    arr.push(el)
  }
 })

However, it didn't work.

I have an array of objects where I want to return only the unique objects based on their object Id.

I've tried to loop in the existing array data then find if the element was already add to a newly created array arr which should contain only the unique values, but it didn't work with me and I believe that I am missing something here or there.

Here is the current array :

          [
        {
          "objectId": "WMtwbyhFI6",
          "cuisineNameEn": "Cafe",
          "ordersNo": 20,
          "hidden": false
        },
        {
          "objectId": "QJSNTMpq5F",
          "ordersNo": 24,
          "cuisineNameEn": "Italian",
          "hidden": false
        },
        {
          "objectId": "iLXKswFRGa",
          "ordersNo": 5,
          "cuisineNameEn": "Japanese",
          "hidden": true
        },
        {
          "objectId": "Db0MeihpJE",
          "ordersNo": 6,
          "cuisineNameEn": "Fast Food",
          "hidden": false
        },
        {
          "objectId": "QJSNTMpq5F",
          "ordersNo": 24,
          "cuisineNameEn": "Italian",
          "hidden": false
        },
        {
          "objectId": "Db0MeihpJE",
          "ordersNo": 6,
          "cuisineNameEn": "Fast Food",
          "hidden": false
        },
        {
          "objectId": "Db0MeihpJE",
          "ordersNo": 6,
          "cuisineNameEn": "Fast Food",
          "hidden": false,
        },
        {
          "objectId": "Db0MeihpJE",
          "ordersNo": 6,
          "cuisineNameEn": "Fast Food",
          "hidden": false
        },
         {
          "objectId": "Db0MeihpJE",
          "ordersNo": 6,
          "cuisineNameEn": "Fast Food",
          "hidden": false
        },
         {
          "objectId": "Db0MeihpJE",
          "ordersNo": 6,
          "cuisineNameEn": "Fast Food",
          "hidden": false
        },
        {
          "objectId": "Db0MeihpJE",
          "ordersNo": 6,
          "cuisineNameEn": "Fast Food",
          "hidden": false
        }
      ]

However, this is what I want to return :

 [
        {
          "objectId": "WMtwbyhFI6",
          "cuisineNameEn": "Cafe",
          "ordersNo": 20,
          "hidden": false
        },
        {
          "objectId": "iLXKswFRGa",
          "ordersNo": 5,
          "cuisineNameEn": "Japanese",
          "hidden": true
        },
        {
          "objectId": "Db0MeihpJE",
          "ordersNo": 6,
          "cuisineNameEn": "Fast Food",
          "hidden": false
        },
        {
          "objectId": "QJSNTMpq5F",
          "ordersNo": 24,
          "cuisineNameEn": "Italian",
          "hidden": false
        }
      ]

I've tried the following:

 var arr = [];
  data.forEach((el)=>{
  if (arr.indexOf(el.objectId) === -1) {
    arr.push(el)
  }
 })

However, it didn't work.

Share Improve this question asked Dec 29, 2017 at 14:59 Hamza L.Hamza L. 1,8234 gold badges27 silver badges47 bronze badges 5
  • @JanS not a duplicate, please read the post carefully, I am willing to return a full object not only an element !!! – Hamza L. Commented Dec 29, 2017 at 15:04
  • 1 @MathRobin not a duplicate I believe he wants to return the object not the element. – Folky.H Commented Dec 29, 2017 at 15:06
  • indexOf() won't inspect properties inside the array elements. It can only check whole element equality – charlietfl Commented Dec 29, 2017 at 15:07
  • @MichałPerłakowski I don't think it is a duplicate as except one all the answers are using some library – brk Commented Dec 29, 2017 at 15:21
  • Do you want to return the first or the last found one? – Jonas Wilms Commented Dec 29, 2017 at 15:33
Add a comment  | 

6 Answers 6

Reset to default 10

Use the reduce() method:

data.reduce((acc, x) =>
   acc.concat(acc.find(y => y.ordersNo === x.ordersNo) ? [] : [x])
 , []);

reduce goes through the array, and for each element it calls the provided function with accumulator (the return value of the previous call) and the current element. concat adds the current element to the accumulator if it doesn't exist there yet. find checks if the current element exists in the accumulator by comparing the ordersNo properties.

Demo:

const data =           [
        {
          "objectId": "WMtwbyhFI6",
          "cuisineNameEn": "Cafe",
          "ordersNo": 20,
          "hidden": false
        },
        {
          "objectId": "QJSNTMpq5F",
          "ordersNo": 24,
          "cuisineNameEn": "Italian",
          "hidden": false
        },
        {
          "objectId": "iLXKswFRGa",
          "ordersNo": 5,
          "cuisineNameEn": "Japanese",
          "hidden": true
        },
        {
          "objectId": "Db0MeihpJE",
          "ordersNo": 6,
          "cuisineNameEn": "Fast Food",
          "hidden": false
        },
        {
          "objectId": "QJSNTMpq5F",
          "ordersNo": 24,
          "cuisineNameEn": "Italian",
          "hidden": false
        },
        {
          "objectId": "Db0MeihpJE",
          "ordersNo": 6,
          "cuisineNameEn": "Fast Food",
          "hidden": false
        },
        {
          "objectId": "Db0MeihpJE",
          "ordersNo": 6,
          "cuisineNameEn": "Fast Food",
          "hidden": false,
        },
        {
          "objectId": "Db0MeihpJE",
          "ordersNo": 6,
          "cuisineNameEn": "Fast Food",
          "hidden": false
        },
         {
          "objectId": "Db0MeihpJE",
          "ordersNo": 6,
          "cuisineNameEn": "Fast Food",
          "hidden": false
        },
         {
          "objectId": "Db0MeihpJE",
          "ordersNo": 6,
          "cuisineNameEn": "Fast Food",
          "hidden": false
        },
        {
          "objectId": "Db0MeihpJE",
          "ordersNo": 6,
          "cuisineNameEn": "Fast Food",
          "hidden": false
        }
      ];
 
 console.log(data.reduce((acc, x) =>
   acc.concat(acc.find(y => y.ordersNo === x.ordersNo) ? [] : [x])
 , []));

You may filter the array and use a Set of ids to check for dupes:

const result = array.filter( (hash => obj => !(hash.has(obj.objectId) || hash.add(obj.objectId) && false))(new Set));

You can use array#reduce and create an object with objectId as the key and the object as the values. Once, you have your object, extract all values to get the unique objects using Object.values().

var data = [ { "objectId": "WMtwbyhFI6", "cuisineNameEn": "Cafe", "ordersNo": 20, "hidden": false }, { "objectId": "QJSNTMpq5F", "ordersNo": 24, "cuisineNameEn": "Italian", "hidden": false }, { "objectId": "iLXKswFRGa", "ordersNo": 5, "cuisineNameEn": "Japanese","hidden": true }, { "objectId": "Db0MeihpJE", "ordersNo": 6, "cuisineNameEn": "Fast Food", "hidden": false }, { "objectId": "QJSNTMpq5F", "ordersNo": 24, "cuisineNameEn": "Italian", "hidden": false }, { "objectId": "Db0MeihpJE", "ordersNo": 6, "cuisineNameEn":"Fast Food", "hidden": false }, { "objectId": "Db0MeihpJE", "ordersNo": 6, "cuisineNameEn": "Fast Food", "hidden": false, }, { "objectId": "Db0MeihpJE", "ordersNo": 6, "cuisineNameEn": "Fast Food", "hidden": false }, { "objectId": "Db0MeihpJE", "ordersNo":6, "cuisineNameEn": "Fast Food", "hidden": false }, { "objectId": "Db0MeihpJE", "ordersNo": 6, "cuisineNameEn": "Fast Food", "hidden": false }, { "objectId": "Db0MeihpJE", "ordersNo": 6, "cuisineNameEn": "Fast Food", "hidden": false } ],
    result = Object.values(data.reduce((r,o) => (r[o.objectId] = o, r),{}));
console.log(result);
.as-console-wrapper { max-height: 100% !important; top: 0; }

You should try with filter and Set :

result = (function () { // we use an IIFE to isolate everything
    var uniqIds = new Set(); // Set only accepts unique values
    return list.filter(item => { // Array filter returns a new array based on result of callback passed in parameter
        if(!uniqIds.has(item.objectId)) {
            uniqIds.add(item.objectId);
            return true;
        } else {
            return false;
        }
    });
}());

indexOf() won't work to check similar objects or check properties inside objects. It will only work with object references that are the same

Can use a hashmap object that stores the common property as keys. Following uses this argument of filter for the hashmap

const res = data.filter(o => !this[o.objectId] && (this[o.objectId]=true), {});

console.log(res);
<script>
const data = [
        {
          "objectId": "WMtwbyhFI6",
          "cuisineNameEn": "Cafe",
          "ordersNo": 20,
          "hidden": false
        },
        {
          "objectId": "QJSNTMpq5F",
          "ordersNo": 24,
          "cuisineNameEn": "Italian",
          "hidden": false
        },
        {
          "objectId": "iLXKswFRGa",
          "ordersNo": 5,
          "cuisineNameEn": "Japanese",
          "hidden": true
        },
        {
          "objectId": "Db0MeihpJE",
          "ordersNo": 6,
          "cuisineNameEn": "Fast Food",
          "hidden": false
        },
        {
          "objectId": "QJSNTMpq5F",
          "ordersNo": 24,
          "cuisineNameEn": "Italian",
          "hidden": false
        },
        {
          "objectId": "Db0MeihpJE",
          "ordersNo": 6,
          "cuisineNameEn": "Fast Food",
          "hidden": false
        },
        {
          "objectId": "Db0MeihpJE",
          "ordersNo": 6,
          "cuisineNameEn": "Fast Food",
          "hidden": false,
        },
        {
          "objectId": "Db0MeihpJE",
          "ordersNo": 6,
          "cuisineNameEn": "Fast Food",
          "hidden": false
        },
         {
          "objectId": "Db0MeihpJE",
          "ordersNo": 6,
          "cuisineNameEn": "Fast Food",
          "hidden": false
        },
         {
          "objectId": "Db0MeihpJE",
          "ordersNo": 6,
          "cuisineNameEn": "Fast Food",
          "hidden": false
        },
        {
          "objectId": "Db0MeihpJE",
          "ordersNo": 6,
          "cuisineNameEn": "Fast Food",
          "hidden": false
        }
      ];
</script>

You can also use this simple solution

function uniqueObjectsArr(array, uniqueValue) {
    var obj = {},
    uniqueArr = [];
    array.forEach(element => {
        obj[element[uniqueValue]] = element;
    });
    for (var key in obj) {
        if (obj.hasOwnProperty(key)) {
            uniqueArr.push(obj[key]);
        }
    }
    return uniqueArr;
}

 myData = uniqueObjectsArr(myData, "objectId");
 console.log(myData);
 <script>
 myData = [
        {
          "objectId": "WMtwbyhFI6",
          "cuisineNameEn": "Cafe",
          "ordersNo": 20,
          "hidden": false
        },
        {
          "objectId": "QJSNTMpq5F",
          "ordersNo": 24,
          "cuisineNameEn": "Italian",
          "hidden": false
        },
        {
          "objectId": "iLXKswFRGa",
          "ordersNo": 5,
          "cuisineNameEn": "Japanese",
          "hidden": true
        },
        {
          "objectId": "Db0MeihpJE",
          "ordersNo": 6,
          "cuisineNameEn": "Fast Food",
          "hidden": false
        },
        {
          "objectId": "QJSNTMpq5F",
          "ordersNo": 24,
          "cuisineNameEn": "Italian",
          "hidden": false
        },
        {
          "objectId": "Db0MeihpJE",
          "ordersNo": 6,
          "cuisineNameEn": "Fast Food",
          "hidden": false
        },
        {
          "objectId": "Db0MeihpJE",
          "ordersNo": 6,
          "cuisineNameEn": "Fast Food",
          "hidden": false,
        },
        {
          "objectId": "Db0MeihpJE",
          "ordersNo": 6,
          "cuisineNameEn": "Fast Food",
          "hidden": false
        },
         {
          "objectId": "Db0MeihpJE",
          "ordersNo": 6,
          "cuisineNameEn": "Fast Food",
          "hidden": false
        },
         {
          "objectId": "Db0MeihpJE",
          "ordersNo": 6,
          "cuisineNameEn": "Fast Food",
          "hidden": false
        },
        {
          "objectId": "Db0MeihpJE",
          "ordersNo": 6,
          "cuisineNameEn": "Fast Food",
          "hidden": false
        }
      ]
      </script>

发布评论

评论列表(0)

  1. 暂无评论