【问题标题】:Javascript - Return only unique values in an array of objectsJavascript - 仅返回对象数组中的唯一值
【发布时间】:2017-12-29 14:59:55
【问题描述】:

我有一个对象数组,我想只返回基于对象 ID 的唯一对象。

我尝试在现有数组 data 中循环,然后查找该元素是否已添加到新创建的数组 arr 中,该数组应仅包含唯一值,但它不适用于我和我相信我在这里或那里遗漏了一些东西。

这是当前数组:

          [
        {
          "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
        }
      ]

但是,这是我想要返回的:

 [
        {
          "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
        }
      ]

我尝试了以下方法:

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

但是,它不起作用。

【问题讨论】:

  • @JanS 不是重复的,请仔细阅读帖子,我愿意返回一个完整的对象而不仅仅是一个元素!!!
  • @MathRobin 不是重复的我相信他想返回对象而不是元素。
  • indexOf() 不会检查数组元素内的属性。它只能检查整个元素是否相等
  • @MichałPerłakowski 我不认为这是重复的,因为除了一个所有答案都在使用某个库
  • 您要返回第一个还是最后一个找到的?

标签: javascript arrays


【解决方案1】:

使用reduce() method

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

reduce 遍历数组,并且对于每个元素,它使用累加器(上一次调用的返回值)和当前元素调用提供的函数。 concat 将当前元素添加到累加器中,如果它尚不存在。 find 通过比较 ordersNo 属性来检查当前元素是否存在于累加器中。

演示:

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])
 , []));

【讨论】:

  • 你能提供一些细节吗?我想了解
  • Array.prototype.reduce() 是最被低估的数组函数。这应该是公认的答案。
  • @TJBlackman 如果你喜欢这个函数,你可能会喜欢函数式编程。我推荐学习Ramda——它是一个用于 JavaScript 的函数库。
  • @TJBlackman reduce 是被滥用最多的数组函数。在这里使用累加器是没有意义的。没有减少:(acc => data.forEach(el => acc.find(e => e.objectId === el.ObjectId) || acc.push(el)) || acc)([])
  • @TJBlackman well...(好吧有一个小错字导致了故障),但是仍然没有减少jeed。
【解决方案2】:

您可以filter 数组并使用一组 id 来检查是否有欺骗:

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

【讨论】:

  • @hamza 你可能会读到closuresIIFESetshort-circuitinglogical operatorsArray.prototype.filter
  • 令人兴奋:)。为什么new Set 不带括号会返回一个集合?
  • @wostex 因为您可以使用new 省略实例构造中的()
  • 为什么在这里省略()?包括它们似乎只会让事情更清楚,它只会让你的代码更长 2 个字符。
  • @bsinky 为什么不呢?我不认为new Set()new Set 更具可读性
【解决方案3】:

您可以使用array#reduce 创建一个以objectId 为键、对象为值的对象。一旦有了对象,提取所有值以使用 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; }

【讨论】:

  • 我认为你应该使用reduceRight
  • 有什么具体原因吗?
  • 好吧,他想要所有唯一的对象,所以,即使是这段代码也应该可以工作。我明白你的意思。
【解决方案4】:

您应该尝试使用 filter 和 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;
        }
    });
}());

【讨论】:

    【解决方案5】:

    indexOf() 无法检查相似对象或检查对象内部的属性。它只适用于相同的对象引用

    可以使用将公共属性存储为键的 hashmap 对象。以下使用filterthis 参数作为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>

    【讨论】:

      【解决方案6】:

      您也可以使用这个简单的解决方案

      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>

      【讨论】:

        猜你喜欢
        • 2021-02-26
        • 1970-01-01
        • 1970-01-01
        • 2017-04-15
        • 2013-06-25
        • 1970-01-01
        • 1970-01-01
        • 2017-11-16
        • 2018-04-11
        相关资源
        最近更新 更多