问题
How can I filler the below array on common id
and output should have unique and latest history number
const input = [{
"id": 134116,
"user": "admin",
"historyno": "134116-0"
}, {
"id": 134132,
"user": "admin",
"historyno": "134132-0"
}, {
"id": 134132,
"user": "admin",
"historyno": "134132-1"
}, {
"id": 134133,
"user": "admin",
"historyno": "134133-0"
}, {
"id": 134133,
"user": "admin",
"historyno": "134133-1"
}];
let output = [];
let tempId;
for (let i = 0; i < input.length; i++) {
if (input[i].id === tempId) {
//do nothing
} else {
output.push(input[i]);
tempId = input[i].id;
}
}
console.log(output);
Expected Output
[
{
"id": 134116,
"user": "admin",
"historyno": "134116-0"
},
{
"id": 134132,
"user": "admin",
"historyno": "134132-1"
},
{
"id": 134133,
"user": "admin",
"historyno": "134133-1"
}
]
回答1:
Reduce the array to a Map, using the id
as key, and then convert back by spreading the Map.values()
iterator to an array.
This solution assumes that the array is presorted by history numbers:
const input = [{"id":134116,"user":"admin","historyno":"134116-0"},{"id":134132,"user":"admin","historyno":"134132-0"},{"id":134132,"user":"admin","historyno":"134132-1"},{"id":134133,"user":"admin","historyno":"134133-0"},{"id":134133,"user":"admin","historyno":"134133-1"}];
const output = [...input.reduce((r, o) => r.set(o.id, o), new Map).values()];
console.log(output);
This solution handles unsorted arrays by only replacing the current item in the map if historyno
is greater:
const input = [{"id":134116,"user":"admin","historyno":"134116-0"},{"id":134132,"user":"admin","historyno":"134132-0"},{"id":134132,"user":"admin","historyno":"134132-1"},{"id":134133,"user":"admin","historyno":"134133-0"},{"id":134133,"user":"admin","historyno":"134133-1"}];
const getHistoryNo = ({ historyno }) => +historyno.split('-')[1];
const output = [...input.reduce((r, o) => {
const prev = r.get(o.id);
if(!prev || getHistoryNo(o) > getHistoryNo(prev)) r.set(o.id, o);
return r;
}, new Map).values()];
console.log(output);
回答2:
You can split historyno
by -
and take the second element, compare it with previously set same id's value, if the current one is higher than last one use the current one else use the last one
const input = [{"id": 134116,"user": "admin","historyno": "134116-0"}, { "id": 134132, "user": "admin","historyno": "134132-0"}, { "id": 134132,"user": "admin","historyno": "134132-1"}, { "id": 134133, "user": "admin", "historyno": "134133-0"
}, { "id": 134133,"user": "admin","historyno": "134133-1"}];
let final = input.reduce((op,inp)=>{
op[inp.id] = op[inp.id] || inp
let lastHisotry = +op[inp.id].historyno.split('-')[1]
let currentHistory = +inp.historyno.split('-')[1]
op[inp.id].historyno = currentHistory > lastHisotry ? inp.historyno : op[inp.id].historyno
return op
},{})
console.log(final);
Note:- If your array is already ordered you don't need this split logic, you can simply do
const input = [{"id": 134116,"user":"admin","historyno": "134116-0"}, { "id": 134132, "user":"admin","historyno": "134132-0"}, { "id": 134132,"user": "admin","historyno": "134132-1"}, { "id": 134133, "user": "admin", "historyno": "134133-0"}, { "id": 134133,"user": "admin","historyno": "134133-1"}];
let final = input.reduce((op,inp) => {
op[inp.id] = inp
return op
},{})
console.log(final);
回答3:
var resultObj = input.reduce((prev, next) => {
if(prev.hasOwnProperty(next.id)) {
const currentLatest = prev[next.id];
// Your logic to check if 'currentLatest' is the latest one or the 'next'
} else {
prev[next.id] = next;
}
return prev;
}, {});
var result = Object.values(resultObj)
来源:https://stackoverflow.com/questions/57169725/how-to-create-a-unique-array-of-json-objects-with-sort-on-a-field