1

I have a Vue.js web app that consumes data from an express.js API and shows the response array in a table. Each object of the array has unique id formed by Name_Version (for example P.90.001000-0004_2). The problem is that I need to show only the last version of each one. For example, if the API response is:

[{id: P.90.001000-0004_1}, {id: P.90.001000-0004_2}, {id: P.90.001000-0004_3}, {id: P.90.002222-0025_1}, {id: P.90.002222-0025_2}]

the result array to show in the table would be:

[{id: P.90.001000-0004_3}, {id: P.90.002222-0025_2}]

It's been impossible for me to achieve this result, can anyone please help me?

1
  • 1
    That is a very bad format received from an API. I would migrate the grouping logic to the server rather than the client, otherwise you need to manually split the ids and get the latest one, which is somewhat expensive and senseless on the client side.
    – briosheje
    Commented Dec 5, 2019 at 11:30

2 Answers 2

2

You can build an object that maps the portion of the id without the version to the entire object, and you can keep in this map only the latest version of each item:

const data = [{id: 'P.90.001000-0004_1'}, {id: 'P.90.001000-0004_2'}, {id: 'P.90.001000-0004_3'}, {id: 'P.90.002222-0025_1'}, {id: 'P.90.002222-0025_2'}];
const map = {};

data.forEach((item) => {
  const [id, version] = item.id.split('_');
  const latestItem = map[id];
  
  if (!latestItem || latestItem.id.split('_')[1] < version) {
    map[id] = item;
  }
});

const filteredData = Object.values(map);
console.log(filteredData);

4
  • 1
    You should ensure that _ has only one occurrence, otherwise you should take the lastIndexOf of it.
    – briosheje
    Commented Dec 5, 2019 at 12:29
  • 1
    Also, I guess you should also consider the case where no _ exists in case there only is one instance and, for some reason, whoever made such API thought the _ was not needed.
    – briosheje
    Commented Dec 5, 2019 at 13:21
  • 1
    _ has only one occurrence in each object and all of them has that termination (from _0 to _X) so you can obviate this two things. Said that, this solution works perfectly. Thank you very very much!! Commented Dec 5, 2019 at 15:25
  • @titanlux619 Glad to help :) Commented Dec 5, 2019 at 15:31
2

You can use reduce to get the latest version, and then use Object.entries with map and join to put them back into format:

const arr = [{id: 'P.90.001000-0004_1'}, {id: 'P.90.001000-0004_2'}, {id: 'P.90.001000-0004_3'}, {id: 'P.90.002222-0025_1'}, {id: 'P.90.002222-0025_2'}]


const latest = arr.reduce((a, {id}) => {
  const [k,v] = id.split('_')
  a[k] = +v > (a[k] || 0) ? v : a[k]
  return a
}, {})

const output = Object.entries(latest).map(pair => ({ id: pair.join('_')}))

console.log(output)

If you need to keep the rest of the properties, you can use a map, and keep reference to the original object by index:

const arr = [{id: 'P.90.001000-0004_1'}, {id: 'P.90.001000-0004_2'}, {id: 'P.90.001000-0004_3'}, {id: 'P.90.002222-0025_1'}, {id: 'P.90.002222-0025_2'}]

const latest = arr.reduce((a, {id}, i) => {
  const [k,v] = id.split('_')
  if(!a.has(k) || +v > a.get(k)[0]) a.set(k, [+v, i])
  return a
}, new Map())

const output = [...latest.values()].map(([,i]) => arr[i])

console.log(output)

3
  • This solution works, but the result array only contains de property id and each object has 15 more properties that I need to show in the table. how can I keep the rest of the properties of each object? Commented Dec 5, 2019 at 12:48
  • @titanlux619 Check my answer now 👍
    – Kobe
    Commented Dec 5, 2019 at 14:04
  • This solution return the same number of objects that your previous solution and all properties of each object but there are a lot of duplicates. I tried to modify and improve it with no luck. @Alberto Trinidade Tavares's answer works like a charm anyways. Thank you very much to you too! Commented Dec 5, 2019 at 15:32

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.