简体   繁体   中英

How to create a unique array of json objects with sort on a field?

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

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); 

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); 

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)

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM