【问题标题】:Filter array and get first values as array of object for unique id过滤数组并获取第一个值作为唯一 id 的对象数组
【发布时间】:2016-10-08 08:13:46
【问题描述】:

我有以下数组 例如,我只需要返回唯一 ID,因为在这个数组中我有 两次 id 1 & 3 我需要只有第一个 findigs id 的新数组,

在这个例子中,前 3 个条目,我如何将它与 maps/filter 一起使用,而不是与常规 for 一起使用

var oData = [{
  id: 1,
  ListTypeGroupDescription: 2,
  test: 111,
  test2: 222
}, {
  id: 2,
  ListTypeGroupDescription: 4,
  test: 333,
  test2: 444
}, {
  id: 3,
  ListTypeGroupDescription: 6,
  test: 666,
  test2: 777
}, {
  id:1,
  ListTypeGroupDescription: 99,
  test: 666,
  test2: 777
}, {
  id: 3,
  ListTypeGroupDescription: 99,
  test: 666,
  test2: 777
}];


var data = oData.map(
  function(obj) {
    return obj.id;
  }
);

http://jsfiddle.net/5qu0j8g0/1/

地图只返回 ID,但我需要所有对象

我需要这个新数组

var oNew = [{
  id: 1,
  ListTypeGroupDescription: 2,
  test: 111,
  test2: 222
}, {
  id: 2,
  ListTypeGroupDescription: 4,
  test: 333,
  test2: 444
}, {
  id: 3,
  ListTypeGroupDescription: 6,
  test: 666,
  test2: 777
}
]

【问题讨论】:

  • 请试试我的回答

标签: javascript arrays dictionary functional-programming


【解决方案1】:

您可以在使用this 处理的回调中使用Array#filter 和一个临时哈希表Object.create(null))(一个没有任何原型的真正空对象)对其进行过滤。

filter() 方法创建一个新数组,其中包含通过所提供函数实现的测试的所有元素。

var oData = [{ id: 1, ListTypeGroupDescription: 2, test: 111, test2: 222 }, { id: 2, ListTypeGroupDescription: 4, test: 333, test2: 444 }, { id: 3, ListTypeGroupDescription: 6, test: 666, test2: 777 }, { id: 1, ListTypeGroupDescription: 99, test: 666, test2: 777 }, { id: 3, ListTypeGroupDescription: 99, test: 666, test2: 777 }],
    oNew = oData.filter(function (a) {
        if (!this[a.id]) {
            this[a.id] = true;
            return true;
        }
    }, Object.create(null));

console.log(oNew);

ES6

var oData = [{ id: 1, ListTypeGroupDescription: 2, test: 111, test2: 222 }, { id: 2, ListTypeGroupDescription: 4, test: 333, test2: 444 }, { id: 3, ListTypeGroupDescription: 6, test: 666, test2: 777 }, { id: 1, ListTypeGroupDescription: 99, test: 666, test2: 777 }, { id: 3, ListTypeGroupDescription: 99, test: 666, test2: 777 }],
    oNew = oData.filter((temp => a => !temp[a.id] && (temp[a.id] = true))(Object.create(null)));

console.log(oNew);

【讨论】:

  • 首先,这种方法是迄今为止所有答案中最好的。我认为它在时间复杂度方面不会变得更好。使用与过滤功能集成的哈希表很聪明。它减少了多余的indexOf 搜索。但是我真的很喜欢你的 IIFE 发明,因为你不能按预期使用带有箭头的 temp 对象。感谢您尝试将所有内容都包含在过滤方法中。良好的功能方法。 +
【解决方案2】:

Array.map 函数将返回一个与初始数组具有相同长度(大小)的新数组。
但是您需要过滤/保留具有唯一 id 属性的元素。
使用Array.forEach 函数将辅助数组(用于ids 列表)作为第二个参数(thisArg):

var oNew = [];

oData.forEach(function(obj){
    if (this.indexOf(obj['id']) === -1) {  // check if current 'id' was processed previously 
        this.push(obj['id']);
        oNew.push(obj);
    }
}, []);

console.log(JSON.stringify(oNew, 0, 4));

输出:

[
    {
        "id": 1,
        "ListTypeGroupDescription": 2,
        "test": 111,
        "test2": 222
    },
    {
        "id": 2,
        "ListTypeGroupDescription": 4,
        "test": 333,
        "test2": 444
    },
    {
        "id": 3,
        "ListTypeGroupDescription": 6,
        "test": 666,
        "test2": 777
    }
]

【讨论】:

    【解决方案3】:

    使用 ECMAScript 6:

    var oData = [{ id: 1, ListTypeGroupDescription: 2, test: 111, test2: 222 }, { id: 2, ListTypeGroupDescription: 4, test: 333, test2: 444 }, { id: 3, ListTypeGroupDescription: 6, test: 666, test2: 777 }, { id: 1, ListTypeGroupDescription: 99, test: 666, test2: 777 }, { id: 3, ListTypeGroupDescription: 99, test: 666, test2: 777 }],
        oNew = oData.filter((obj, index, self) => self.findIndex((o) => { return o.id === obj.id; }) === index);
    
    console.log(oNew);

    【讨论】:

      【解决方案4】:

      这是Unique values in an array 的修改版本。它向 Array 原型添加了一个 getUniqueByID 函数,该函数通过数组中对象的 ID 返回唯一值(注意:这仅适用于已定义的数组喜欢你的):

      Array.prototype.getUniqueByID = function(){
         var u = {}, a = [];
         for(var i = 0, l = this.length; i < l; ++i){
            if(u.hasOwnProperty(this[i].id)) {
               continue;
            }
            a.push(this[i]);
            u[this[i].id] = 1;
         }
         return a;
      }
      
      console.log(oData.getUniqueByID());
      

      【讨论】:

        【解决方案5】:

        这可以工作。

        var keys = [];
        var data = oData.filter(
          function(obj) {
            if(keys.indexOf(obj.id) == -1) {
               keys.push(obj.id)
               return obj;
            }
          }
        );
        

        注意:我也将.map() 更改为.filter()

        【讨论】:

        • 数据将包含完整的对象。如果您注意到,我使用的是 return obj 而不是 return obj.id
        • 你不需要在filter回调函数中返回obj或者obj.id,你只需要返回true或者false,但是当你返回true时整个对象都可用在新数组中。
        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2023-04-10
        • 2022-10-23
        • 2019-06-21
        • 1970-01-01
        相关资源
        最近更新 更多