skip to Main Content

I have an array containing multiple string items. all of them have a format like this:

code1-code2-id-

code1 is different in each string. code2 is always the same.
What I want to do is to remove the elements that have the same id.

Example:

const links = ["13989664-34-1-","3588867-34-1-","4757546-34-2-" ,"72469424-34-2-"]

desired output:

["13989664-34-1-","4757546-34-2-"]

P.S : It doesn’t have to return the first duplicate or the second one. Either one is fine

I have tried this solution and was wondering if there’s a more elegant way to do it

const links = [
  "13989664-34-1-",
  "3588867-34-1-",
  "4757546-34-2-",
  "72469424-34-2-",
];

const uniqueLinks = [];
links.forEach((link, index) => {
  console.log(index);
  const linkId = link.substring(link.length - 2, link.length - 1);
  if (index == 0) uniqueLinks.push(link);
  else if (
    !uniqueLinks.find((l) => l.substring(l.length - 2, l.length - 1) == linkId)
  ) {
    uniqueLinks.push(link);
  }
});

4

Answers


  1. You can use filter and findIndex for that. Ie, keep those elements, where the search for the first occurrence of that elements’s id returns the element’s index. This will always keep the first element with the respective id.

    const links = ["13989664-34-1-","3588867-34-1-","4757546-34-2-" ,"72469424-34-2-"]
    function getId(s) {
      return s.split("-")[2];
    }
    
    
    const filtered= links.filter((l, i) => links.findIndex(x => getId(x) === getId(l)) == i);
    console.log(filtered)

    Thus for "13989664-34-1-" the search for id "1" will return an index of 0 which is the same as the index of "13989664-34-1-" in the array. But when searching for the id "1" of "3588867-34-1-", it will again return 0 (as the first element in the array has id "1"), but the index of "3588867-34-1-" in the array is 1, thus, this element will be removed.

    Login or Signup to reply.
  2. Using a reduce and return the values

    It doesn't have to return the first duplicate or the second one. Either one is fine

    To keep the first we can use the ??= nullish coalescing assignment

    To keep the last found, change ??= to =

    const links = ["13989664-34-1-","3588867-34-1-","4757546-34-2-" ,"72469424-34-2-"]
    const filtered = Object.values(links.reduce((acc,cur) => {
        acc[cur.split("-")[2]] ??= cur;
        return acc;
      } ,{})
    )
    
    console.log(filtered)
    Login or Signup to reply.
  3. const links = ["13989664-34-1-","3588867-34-1-","4757546-34-2-" ,"72469424-34-2-"];
    
    console.log(links.filter((item, index) => {
        return links.filter((innerItem, innerIndex) => {
            return (innerIndex < index) && (item.split("-")[2] === innerItem.split("-")[2])
        }).length === 0;
    }))

    The idea is that we use .filter() in a nested manner, that is, we search for items for which we search for earlier items having the same id and where we do not find such earlier items (.length === 0), we confirm that this is the first item having that id.

    Login or Signup to reply.
  4. Once you extract the key, matching the key in an object would be faster, than looping through a new array to see if the key exists.

    const links = ["13989664-34-1-","3588867-34-1-","4757546-34-2-" ,"72`469424-34-2-"]
    let obj = {}
    let result = []
    links.forEach(el => {
        let key = el.split("-")[2]
        if(!obj[key]){
            result.push(el)
            obj[key] = true
        }
    })
    obj = {}
    console.log("result",result)
    
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search