基于两个条件过滤数组
Filter array based of two conditions
我有以下对象数组,(据说这里的时间是模拟的,更大的是最后一个)
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
}];
如您所见,我已通过两件事过滤此数组
- uniqe ID (the entry 1 & 3 are exist just once)
- timestemp (add just the object with the last timestemp)
如何使用 map/reduce/filter 等数组方法来做到这一点?
我尝试用 array.filter 做,但没有成功
首先你把timestamp拼成了timestemp。
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/
如果这是您想要的答案,请务必按赞和绿勾。
由于需要使用 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
的项目。 state
被传递给 firstArr
中的每个元素。因为结果是一个对象(以 id
作为键,实际项目作为值),我们需要 map
将它返回到数组。
如果 firstArr
按时间戳排序,这将起作用。返回的数组也会按时间戳排序。
从数组末尾(较大的时间戳)开始,如果尚未找到当前元素,则将其包含在新数组中。 found
数组用于跟踪提取的元素。
var found = [];
firstArr.reverse().filter( function(el){
if( found.indexOf( el.id ) === -1 ){
found.push( el.id );
return true;
}
return false;
}).reverse();
groupBy 是你的好友:https://lodash.com/docs#groupBy
_(firstArr)
.groupBy('id')
.map(function(x) {
return _(x).orderBy(x,['timestemp'], ['desc']).head();
})
.value();
您可以使用 orderBy() and 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>
您可以排序,然后过滤第一个出现的 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>
我有以下对象数组,(据说这里的时间是模拟的,更大的是最后一个)
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
}];
如您所见,我已通过两件事过滤此数组
- uniqe ID (the entry 1 & 3 are exist just once)
- timestemp (add just the object with the last timestemp)
如何使用 map/reduce/filter 等数组方法来做到这一点?
我尝试用 array.filter 做,但没有成功
首先你把timestamp拼成了timestemp。
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/
如果这是您想要的答案,请务必按赞和绿勾。
由于需要使用 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
的项目。 state
被传递给 firstArr
中的每个元素。因为结果是一个对象(以 id
作为键,实际项目作为值),我们需要 map
将它返回到数组。
如果 firstArr
按时间戳排序,这将起作用。返回的数组也会按时间戳排序。
从数组末尾(较大的时间戳)开始,如果尚未找到当前元素,则将其包含在新数组中。 found
数组用于跟踪提取的元素。
var found = [];
firstArr.reverse().filter( function(el){
if( found.indexOf( el.id ) === -1 ){
found.push( el.id );
return true;
}
return false;
}).reverse();
groupBy 是你的好友:https://lodash.com/docs#groupBy
_(firstArr)
.groupBy('id')
.map(function(x) {
return _(x).orderBy(x,['timestemp'], ['desc']).head();
})
.value();
您可以使用 orderBy() and 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>
您可以排序,然后过滤第一个出现的 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>