根据两个条件过滤数组

时间:2016-06-08 10:37:01

标签: javascript arrays object javascript-objects lodash

我有以下数组的对象,(比如说这里的时间点是模拟的,而后者是最后一个)

var firstArr = [{
  id: 1,
  a: 2,
  timestemp: 111
}, {
  id: 2,
  a: 4,
  timestemp: 222
}, {
  id: 3,
  a: 6,
  timestemp: 333
}, {
  id: 1,
  a: 3,
  timestemp: 777
}, {
  id: 3,
  a: 5555,
  timestemp: 5555
}];

我需要做的是以某种方式过滤此数组并创建具有唯一值的新数组。

我最后需要

var endArr = [{
  id: 1,
  a: 3,
  timestemp: 777
}, {
  id: 2,
  a: 4,
  timestemp: 222
},  {
  id: 3,
  a: 5555,
  timestemp: 555
}];

正如您所见,我已经通过两件事过滤了这个数组

  
      
  1. uniqe ID(条目1& 3只存在一次)
  2.   
  3. timestemp(仅添加具有最后时间段的对象)
  4.   

我怎样才能使用map / reduce / filter等数组方法呢?

我尝试使用array.filter而没有成功

6 个答案:

答案 0 :(得分:0)

首先,您将时间戳拼写为时间戳。

var firstArr = [{
  id: 1,
  a: 2,
  timestamp: 111
}, {
  id: 2,
  a: 4,
  timestamp: 222
}, {
  id: 3,
  a: 6,
  timestamp: 333
}, {
  id: 1,
  a: 3,
  timestamp: 777
}, {
  id: 3,
  a: 5555,
  timestamp: 5555
}];

这是功能:

function updateList(a_list) {

    var seen = {};

    for (var entry in a_list) {
        var id = a_list[entry]["id"];

        if (seen.hasOwnProperty(id)) {
            var current_timestamp = seen[id]["timestamp"]
            var check_timestamp = a_list[entry]["timestamp"]

            if (current_timestamp < check_timestamp) {
                 seen[id] = a_list[entry];
            }

        } else {
            seen[id] = a_list[entry];
        }
    }

    var updated = [];
    for (var newest in seen) {
        updated.push(seen[newest]);
    } 
    return updated;
} 

https://jsfiddle.net/vpg3onqm/
如果这是你想要的答案,请务必按upvote和greentick。

答案 1 :(得分:0)

由于要求使用filter / map / reduce,我想我会选择:

var lastestPerId = firstArr.reduce(function(state, curr) {
  if(state[curr.id]){ // We've seen this id before
     if(curr.timestemp > state[curr.id].timestemp) { // and its later
        state[curr.id] = curr; // so, update this item to be the latest item
     }
  } else {
     state[curr.id]  = curr; // add because unknown
  }

  return state; // pass along the state to the next item in the array
}, {});

var endArr = Object.keys(lastestPerId)
    .map(function (key) {return bestPerId[key]});

这会创建一个初始状态({}),循环遍历firstArr中的每个项目。它会尝试找出id是否已知,如果已知,它会跟踪(state)具有最高timestemp的项目。 statefirstArr中的每个元素传递id。因为结果是一个对象(以map为键,实际项为值),我们需要{{1}}将其返回数组。

答案 2 :(得分:0)

如果firstArr按时间戳排序,则此方法有效。返回的数组也将按时间戳排序。

从数组的末尾开始(更大的时间戳),如果尚未找到新数组,请包含当前元素。 found数组用于跟踪提取的元素。

var found = [];
firstArr.reverse().filter( function(el){

  if( found.indexOf( el.id ) === -1 ){
    found.push( el.id );
    return true;
  }
  return false;

}).reverse();

答案 3 :(得分:0)

groupBy是你的朋友:https://lodash.com/docs#groupBy

_(firstArr)
  .groupBy('id')
  .map(function(x) {
    return _(x).orderBy(x,['timestemp'], ['desc']).head();
  })
  .value();

https://jsfiddle.net/koljada/53esaqLz/3/

答案 4 :(得分:0)

您可以使用orderBy()uniqBy()来获取具有最新时间戳的唯一ID的所有项目:

var firstArr = [{
  id: 1,
  a: 2,
  timestamp: 111
}, {
  id: 2,
  a: 4,
  timestamp: 222
}, {
  id: 3,
  a: 6,
  timestamp: 333
}, {
  id: 1,
  a: 3,
  timestamp: 777
}, {
  id: 3,
  a: 5555,
  timestamp: 5555
}];

var result = _(firstArr)
.orderBy(['id', 'timestamp'], ['asc', 'desc'])
.uniqBy('id')
.value();

console.log(result);
<script src="https://cdn.jsdelivr.net/lodash/4.13.1/lodash.min.js"></script>

答案 5 :(得分:0)

您可以排序,然后过滤首次出现的ID:

var firstArr = [
    { id: 1, a: 2, timestemp: 111 },
    { id: 2, a: 4, timestemp: 222 },
    { id: 3, a: 6, timestemp: 333 },
    { id: 1, a: 3, timestemp: 777 },
    { id: 3, a: 5555, timestemp: 5555 }
];

// sort firstArr by decrescent timestamp:
firstArr.sort((x,y)=>y.timestemp-x.timestemp);

// get only the first occurrence of each id:
var endArr = firstArr.filter((o,i)=>i==firstArr.findIndex(u=>u.id==o.id));

// job finished
output.innerHTML = JSON.stringify( endArr, null, 2 );
<pre id=output>