1

I have the following data structure that i receive from the api:

[
  {
    id: '10000844',
    text_id: '10000844-01',
  },
  {
    id: '10000844',
    text_id: '10000844-02',
  },
  {
    id: '12000844',
    text_id: '12000844-03',
  },
  {
    id: '12000844',
    text_id: '12000844-07',
  },
  {
    id: '12000814',
    text_id: '12000844-07',
  },
 {
    id: '12002812',
    text_id: '12000844-07',
  },
   {
    id: '12000814',
    text_id: '12000844-08',
  },
]

The perfect outcome of cleaning the code would be this result, basically returning only the first found id:

[
      {
        id: '10000844',
        text_id: '10000844-01',
      },
      {
        id: '12000844',
        text_id: '12000844-03',
      },
      {
        id: '12000814',
        text_id: '12000844-07',
      },
     {
        id: '12002812',
        text_id: '12000844-07',
      },
    ]

But currently it only returns the last found duplicate in a unique array, with the current code:

let uniqueArray = [...new Map(data.map(item =>
    [item.id, item])).values()];

7 Answers7

4

You can use Object.values() and reduce() same as :

const data = [
  {
    id: '10000844',
    text_id: '10000844-01',
  },
  {
    id: '10000844',
    text_id: '10000844-02',
  },
  {
    id: '12000844',
    text_id: '12000844-03',
  },
  {
    id: '12000844',
    text_id: '12000844-07',
  },
  {
    id: '12000814',
    text_id: '12000844-07',
  },
 {
    id: '12002812',
    text_id: '12000844-07',
  },
   {
    id: '12000814',
    text_id: '12000844-08',
  },
]

const result = Object.values(
  data.reduce((res, {id, text_id}) => {
    res[id] ??= {id, text_id}
    return res
  }, {})
)
console.log(result)

Update with ??= document

The logical nullish assignment (x ??= y) operator only assigns if x is nullish (null or undefined).

Xupitan
  • 1,601
  • 1
  • 8
  • 12
0

You can do it like this:

const arr = [
  {
    id: '10000844',
    text_id: '10000844-01',
  },
  {
    id: '10000844',
    text_id: '10000844-02',
  },
  {
    id: '12000844',
    text_id: '12000844-03',
  },
  {
    id: '12000844',
    text_id: '12000844-07',
  },
  {
    id: '12000814',
    text_id: '12000844-07',
  },
 {
    id: '12002812',
    text_id: '12000844-07',
  },
   {
    id: '12000814',
    text_id: '12000844-08',
  },
];
const unique = [];
const visited = new Set();
for(let i = 0; i < arr.length; ++i){
  if(!visited.has(arr[i].id)){
    unique.push(arr[i]);
    visited.add(arr[i].id);
  }
}

console.log(unique);
mgm793
  • 1,968
  • 15
  • 23
0

Concept

Loop through all the objects in the data and check if the id is found in result array. If not found then push it into the result array; otherwise, skip it.

Code

const data = [{
    id: '10000844',
    text_id: '10000844-01',
  },
  {
    id: '10000844',
    text_id: '10000844-02',
  },
  {
    id: '12000844',
    text_id: '12000844-03',
  },
  {
    id: '12000844',
    text_id: '12000844-07',
  },
  {
    id: '12000814',
    text_id: '12000844-07',
  },
  {
    id: '12002812',
    text_id: '12000844-07',
  },
  {
    id: '12000814',
    text_id: '12000844-08',
  },
];
let result = [];
let found;
data.forEach(d => {
  found = false;
  result.forEach(r => {
    if (!found && r.id === d.id) found = true;
  })
  if (!found) result.push(d);
});
console.log(result);
holydragon
  • 6,158
  • 6
  • 39
  • 62
0

You can reduce the array into an object that stores only the first occurrence of every id and then extract the values from this object.

const 
  data = [{ id: "10000844", text_id: "10000844-01" }, { id: "10000844", text_id: "10000844-02" }, { id: "12000844", text_id: "12000844-03" }, { id: "12000844", text_id: "12000844-07" }, { id: "12000814", text_id: "12000844-07" }, { id: "12002812", text_id: "12000844-07" }, { id: "12000814", text_id: "12000844-08" }],
  result = Object.values(data.reduce((acc, d) => (!acc[d.id] ? { ...acc, [d.id]: d } : acc), {}));

console.log(result);
SSM
  • 2,855
  • 1
  • 3
  • 10
  • You may want to document how that one-liner works since it will be gibberish to beginners. – Andy Jun 29 '22 at 06:55
0

Here is another way to achieve you desire output.
we use reduce for changing in data and use find function to get current id is already in prev or not if not then we use filter function to filter out same id object and push only first.

const data =[
  {
    id: '10000844',
    text_id: '10000844-01',
  },
  {
    id: '10000844',
    text_id: '10000844-02',
  },
  {
    id: '12000844',
    text_id: '12000844-03',
  },
  {
    id: '12000844',
    text_id: '12000844-07',
  },
  {
    id: '12000814',
    text_id: '12000844-07',
  },
 {
    id: '12002812',
    text_id: '12000844-07',
  },
   {
    id: '12000814',
    text_id: '12000844-08',
  },
]

const newData = data.reduce((prev, curr, index, arr) => {
  const find = prev.find(p => p.id === curr.id);
  if (!find) {
    const filter = arr.filter(f => f.id === curr.id);
    if (filter.length >= 1) {
      prev.push(filter[0])
    }
  }
  return prev;
}, [])

console.log(newData)
Mohit Sharma
  • 622
  • 6
  • 11
0

Some of the answers are already correct.

THIS ANSWER IS ONLY IF YOU ARE USING LODASH

You can use uniqBy.

This will return a duplicate-free version of an array where the first occurrence is the one that will be kept:

So in your case, something like

import uniqBy from 'lodash/uniqBy';

// dataFromAPI is your sample data
const unqiueArray = uniqBy(dataFromAPI, 'id');
I am L
  • 4,288
  • 6
  • 32
  • 49
0

Sometimes a simple loop is the way forward.

  1. Create a temporary object
  2. Iterate over the data adding objects to that object if their key can't be found.
  3. Get the values of the output object

const data=[{id:"10000844",text_id:"10000844-01"},{id:"10000844",text_id:"10000844-02"},{id:"12000844",text_id:"12000844-03"},{id:"12000844",text_id:"12000844-07"},{id:"12000814",text_id:"12000844-07"},{id:"12002812",text_id:"12000844-07"},{id:"12000814",text_id:"12000844-08"}];

// Initialise the output object
const out = {};

// Loop over the array of objects
for (const obj of data) {

  // For each object destructure the id from the rest
  // of its properties 
  const { id, ...rest } = obj;

  // If there is no property on the output
  // object with that key create it by adding
  // an object composed of the id and the other
  // object properties to it
  out[id] ??= { id, ...rest };
}

// Now return an array of
// the output object's values
console.log(Object.values(out));

Additional documentation

Andy
  • 61,948
  • 13
  • 68
  • 95