Reputation: 2675
I have an array of objects.
const arr = [
{ title: "sky", artist: "Jon", id: 1 },
{ title: "rain", artist: "Paul", id: 2 },
{ title: "sky", artist: "Jon", id: 1 }
];
I would like to remove all duplicates from the array based on id. The final result should be
[{ title: "rain", artist: "Paul", id: 2 }]
If the array is
const arr = [
{ title: "sky", artist: "Jon", id: 1 },
{ title: "rain", artist: "Paul", id: 2 },
{ title: "sky", artist: "Jon", id: 1 },
{ title: "rain", artist: "Paul", id: 2 },
];
The result should be an [].
This is what I tried:
const arr = [{
title: "sky",
artist: "Jon",
id: 1
},
{
title: "rain",
artist: "Paul",
id: 2
},
{
title: "sky",
artist: "Jon",
id: 1
}
];
const uniqueScenarios = Array.from(new Set(arr.map(a => a.id)))
.map(id => {
return arr.find(a => a.id === id)
})
console.log(uniqueScenarios)
const arr1 = [{
title: "sky",
artist: "Jon",
id: 1
},
{
title: "rain",
artist: "Paul",
id: 2
},
{
title: "sky",
artist: "Jon",
id: 1
},
{
title: "rain",
artist: "Paul",
id: 2
}
];
const uniqueScenarios1 = Array.from(new Set(arr1.map(a => a.id)))
.map(id => {
return arr1.find(a => a.id === id)
})
console.log(uniqueScenarios1)
Please advice. I am open to lodash solutions as well. This is the final solution I am expecting. I am able to add Stackblitz link
Upvotes: 0
Views: 130
Reputation: 5205
If you know the title
, artist
, id
are gonna be in the same order in each of the object, one solution can be this:
var arrayX=[
{ title: "sky", artist: "Jon", id: 1 },
{ title: "rain", artist: "Paul", id: 2 },
{ title: "sky", artist: "Jon", id: 1 }
];
var newArray = arrayX.map(i=> JSON.stringify(i)); //stringify all the objects so as to compare them
var res = newArray.filter((elem, index)=>{
if(newArray.indexOf(elem) === newArray.lastIndexOf(elem)){
return elem //get only those elements whihc do not have dupes
}
});
var finalResult = res.map(i=>JSON.parse(i)); //parse the result to get the array of object
console.log(finalResult)
Upvotes: 0
Reputation: 191976
You can group the items by id
, and then use _.flatMap()
to convert back a single array. In the _.flatMap()
callback return an empty array if the group has more than one item:
const fn = arr => _.flatMap(
_.groupBy(arr, 'id'), // group by the id
group => _.size(group) > 1 ? [] : group // check the size and return an empty array for groups with more than a single item
)
const arr1 = [{"title":"sky","artist":"Jon","id":1},{"title":"rain","artist":"Paul","id":2},{"title":"sky","artist":"Jon","id":1}]
const arr2 = [{"title":"sky","artist":"Jon","id":1},{"title":"rain","artist":"Paul","id":2},{"title":"sky","artist":"Jon","id":1},{"title":"rain","artist":"Paul","id":2}]
console.log(fn(arr1))
console.log(fn(arr2))
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.15/lodash.js"></script>
Another example
Upvotes: 0
Reputation: 386560
You could take an object and filter with the value of the hash table.
const
array = [{ title: "sky", artist: "Jon", id: 1 }, { title: "rain", artist: "Paul", id: 2 }, { title: "sky", artist: "Jon", id: 1 }, { title: "rain", artist: "Paul", id: 2 }],
ids = array.reduce((r, { id }) => (r[id] = !(id in r), r), {}),
result = array.filter(({ id }) => ids[id]);
console.log(result);
Upvotes: 2
Reputation: 801
you can sort the data by id,then each item that has different id
compared with next element and prev element should be added to the result array.
const arr = [
{ title: 'sky', artist: 'Jon', id: 1 },
{ title: 'rain', artist: 'Paul', id: 2 },
{ title: 'sky', artist: 'Jon', id: 1 },
{ title: 'sky', artist: 'Jon', id: 1 },
{ title: 'rain', artist: 'Paul', id: 2 },
{ title: 'test', artist: 'test', id: 3 },
]
arr.sort((a, b) => a.id - b.id)
var res = []
arr.forEach((item, index) => {
if (index < arr.length - 1 && arr[index + 1]) {
if (item.id === arr[index + 1].id) {
return
}
}
if (index > 0 && arr[index - 1]) {
if (item.id === arr[index - 1].id) {
return
}
}
res.push(item)
})
console.log(res)
output
0: {title: "test", artist: "test", id: 3}
Upvotes: 0
Reputation: 18909
You could run the array through reduce() and then use some to see if you should add if it does not exist, or remove using filter if it does.
Snippet:
const arr = [
{ title: "sky", artist: "Jon", id: 1 },
{ title: "rain", artist: "Paul", id: 2 },
{ title: "sky", artist: "Jon", id: 1 },
{ title: "rain", artist: "Paul", id: 2 },
{ title: "earth", artist: "Frank", id: 3 },
];
const unique = arr.reduce((accumulator, currentValue) => {
// add if we don't have
if (!accumulator.some(x => x.id === currentValue.id)) {
accumulator.push(currentValue);
} else {
// remove if we do
accumulator = accumulator.filter(x => x.id !== currentValue.id);
}
return accumulator;
}, []);
console.info(unique);
Upvotes: 0
Reputation: 132
you can do it in one line like this:
const res = arr.filter(elem => (arr.filter(obj => obj.id === elem.id)).length === 1)
or you can do it like this(better in terms of time complexity):
const arr = [
{ title: "sky", artist: "Jon", id: 1 },
{ title: "rain", artist: "Paul", id: 2 },
{ title: "sky", artist: "Jon", id: 1 },
];
const counts = arr.reduce((counts, curr) => (counts[curr.id] = ++counts[curr.id] || 1, counts), {})
const res = arr.filter(curr => counts[curr.id] === 1)
Upvotes: 0
Reputation: 620
One way to do it, in order to avoid running an exponential loop is to save all values to a new object, and convert that object to a new array.
const combinedObj = arr.reduce((obj, item) => { obj[item.id] = item; return obj; }, {});
const newArray = Object.values(combinedObj)
Upvotes: 0
Reputation: 4464
That's a one-liner:
list.filter(el => list.filter(e => e.title == el.title).length == 1);
const arr = [{
title: "sky",
artist: "Jon",
id: 1
},
{
title: "rain",
artist: "Paul",
id: 2
},
{
title: "sky",
artist: "Jon",
id: 1
}
];
const arr1 = [{
title: "sky",
artist: "Jon",
id: 1
},
{
title: "rain",
artist: "Paul",
id: 2
},
{
title: "sky",
artist: "Jon",
id: 1
},
{
title: "rain",
artist: "Paul",
id: 2
}
];
function removeDupes(list) {
return list.filter(el => list.filter(e => e.id == el.id).length == 1);
}
console.log(removeDupes(arr));
console.log(removeDupes(arr1));
Upvotes: 1