Array stores duplicate elements even after excluding them

74 Views Asked by At

I try to dynamically add elements to an Array. If the element in the Array exists, skip it, if it does not exist, add it. The console.log within the .map() function shows, that values have been added. However, it adds too many.

recipes.js

const getUniqueTags = async (req,res)=>{
    const allRecipes = await Recipe.find({}).select("tag");
    let resultArray =[];
    resultArray = allRecipes.map( recipe =>{
        const tag = recipe.tag;
        if(resultArray.includes(tag)){
            
        }
        else{
            return tag;
        }
    });

    console.log(resultArray);
    res.status(200).json(resultArray)
}

console.log

[ Breakfast, Lunch, Lunch, Breakfast ]

What am I doing wrong? Includes does not work, neither does new Set()

3

There are 3 best solutions below

3
Barmar On BEST ANSWER

You're not updating resultArray during the map() loop. So resultArray.includes(tag) is always false, so you do return tag every time.

Use a Set instead of an array, it automatically removes duplicates.

let resultSet = new Set(allRecipes.map(r => r.tag));

If you want an array, you can convert it at the end:

let resultArray = [...resultSet];

const allRecipes = [{
  tag: "Breakfast"
}, {
  tag: "Lunch",
}, {
  tag: "Dinner",
}, {
  tag: "Breakfast"
}];

let resultSet = new Set(allRecipes.map(r => r.tag));
let resultArray = [...resultSet];
console.log(resultArray);

2
Shaheer Khan On

For Simple array you can use

const uniqueArray=[...new Set(array)];

for Array of objects

const uniqueArray = array.filter((item, index) => {
     return index === array.findIndex(obj => obj['key'] === item['key'])
});

console.log(uniqueArray);
<script>
const array  = [{
  key: "Breakfast"
}, {
  key: "Lunch",
}, {
  key: "Dinner",
}, {
  key: "Breakfast"
}];
</script>

0
Alexander Nenashev On

You can reduce your array while checking duplicates in a set:

const result = allRecipes.reduce((r, {tag}) => (r.set.has(tag) || (r.set.add(tag), r.arr.push(tag)), r), {set: new Set, arr:[]}).arr;

console.log(result);
<script>
const allRecipes = [{
  tag: "Breakfast"
}, {
  tag: "Lunch",
}, {
  tag: "Dinner",
}, {
  tag: "Breakfast"
}];
</script>

It's faster than mapping into a set and converting back to an array, the more the items the faster:

` Chrome/118
--------------------------------------------------------
Alexander   1.00x  |  x10000000  873  891  902  905  905
Barmar      1.41x  |   x1000000  123  125  127  134  139
--------------------------------------------------------
https://github.com/silentmantra/benchmark `

const allRecipes = [
{
  tag: "Breakfast"
}, {
  tag: "Lunch",
}, {
  tag: "Dinner",
}, {
  tag: "Breakfast"
},
{
  tag: "Breakfast"
}, {
  tag: "Lunch",
}, {
  tag: "Dinner",
}, {
  tag: "Breakfast"
},
{
  tag: "Breakfast"
}, {
  tag: "Lunch",
}, {
  tag: "Dinner",
}, {
  tag: "Breakfast"
},
{
  tag: "Breakfast"
}, {
  tag: "Lunch",
}, {
  tag: "Dinner",
}, {
  tag: "Breakfast"
},
];

// @benchmark Barmar
[...new Set(allRecipes.map(r => r.tag))];


// @benchmark Alexander

allRecipes.reduce((r, {tag}) => (r.set.has(tag) || (r.set.add(tag), r.arr.push(tag)), r), {set: new Set, arr:[]}).arr;

/*@end*/eval(atob('e2xldCBlPWRvY3VtZW50LmJvZHkucXVlcnlTZWxlY3Rvcigic2NyaXB0Iik7aWYoIWUubWF0Y2hlcygiW2JlbmNobWFya10iKSl7bGV0IHQ9ZG9jdW1lbnQuY3JlYXRlRWxlbWVudCgic2NyaXB0Iik7dC5zcmM9Imh0dHBzOi8vY2RuLmpzZGVsaXZyLm5ldC9naC9zaWxlbnRtYW50cmEvYmVuY2htYXJrL2xvYWRlci5qcyIsdC5kZWZlcj0hMCxkb2N1bWVudC5oZWFkLmFwcGVuZENoaWxkKHQpfX0='));