Remove duplication of Id? - javascript

Why spread is not removing the duplication from the Items?
I am using spread to merge two variables resultA and resultB. There are two duplicated Id (222) in DataA and DataB which should be removed when using spread. Why it did not happen and how to solve this?
const DataA = [
{ Id: 111, Name: 'A' },
{ Id: 222, Name: 'B' },
{ Id: 333, Name: 'C' }
]
const DataB = [
{ Id: 999, Name: 'A' },
{ Id: 222, Name: 'B' },
{ Id: 444, Name: 'C' }
]
let resultA = (DataA || []).map(item => item.Id);
let resultB = (DataB || []).map(item => item.Id);
const items = [
...resultA,
...resultB,
]
const mapping = {
Total: items.length,
Items: items.map(item => { return { Id: item }})
}
console.log(mapping);
Expected Result:
{ Total: 5,
Items:
[ { Id: 111 },
{ Id: 222 },
{ Id: 333 },
{ Id: 999 },
{ Id: 444 } ]
}

The spread syntax on arrays doesn't remove duplicates. To get the result you wanted, Add a line
items = [...new Set(items)] after items
const DataA = [
{ Id: 111, Name: 'A' },
{ Id: 222, Name: 'B' },
{ Id: 333, Name: 'C' }
]
const DataB = [
{ Id: 999, Name: 'A' },
{ Id: 222, Name: 'B' },
{ Id: 444, Name: 'C' }
]
let resultA = (DataA || []).map(item => item.Id);
let resultB = (DataB || []).map(item => item.Id);
let items = [
...resultA,
...resultB,
]
items = [...new Set(items)] // this will remove duplicates
const mapping = {
Total: items.length,
Items: items.map(item => { return { Id: item }})
}
console.log(mapping);

I don't know where you've read that spread removes duplicates, but it does not. Luckily, there are a number of simple ways to achieve this - below is one option that involves very little modification to your code. Simply wrap the array containing items from the 2 spread arrays in a Set constructor (since I see you're already coding to the ES6 spec).
From MDN:
Set objects are collections of values. You can iterate through the
elements of a set in insertion order. A value in the Set may only
occur once; it is unique in the Set's collection.
Finally, you can simply wrap the Set in Array.from to get back to an array (among other ways to do this).
const DataA = [{
Id: 111,
Name: 'A'
},
{
Id: 222,
Name: 'B'
},
{
Id: 333,
Name: 'C'
}
]
const DataB = [{
Id: 999,
Name: 'A'
},
{
Id: 222,
Name: 'B'
},
{
Id: 444,
Name: 'C'
}
]
let resultA = (DataA || []).map(item => item.Id);
let resultB = (DataB || []).map(item => item.Id);
const items = Array.from(new Set([
...resultA,
...resultB,
]));
const mapping = {
Total: items.length,
Items: items.map(item => {
return {
Id: item
}
})
}
console.log(mapping);

Related

Being able to remove duplicate keys from an array of objects

I have a question about how I can delete the existing elements, for example, in my case "Tallas" is repeated, could you please help me? Thank you very much to those who are willing to help me to solve this problem
const data =
[ { atributos: { Tallas: [{ id: 0, name: 'XS' }, { id: 1, name: 'S' }] }}
, { atributos: { Calzado: [{ id: 0, name: '10' }, { id: 1, name: '9.5' }] }}
, { atributos: { Tallas: [{ id: 0, name: 'XS' }] }}
]
The idea is to have this json format with the last "Tallas" since it is the last one that I added through my dynamic form.
const expected =
[{ atributos: { Calzado: [{ id: 0, name: '10' }, { id: 1, name: '9.5' }] }}
, { atributos: { Tallas: [{ id: 0, name: 'XS' }] }}
]
How do I do this is there a way to do it, I've tried with filter plus the findindex but I can't get to eliminate the repetition of the json res= new.filter((arr, index, self) => index === self.findIndex( (t) => (t.attributes === arr.attributes )))
To unique the array of objects, we can use the Javascript Set module, if the array has complex nested objects, we can stringify each object before creating new Set data. this below function will unique the array of complex objects.
function unique_array(array = []) {
const newSetData = new Set(array.map((e) => JSON.stringify(e)));
return Array.from(newSetData).map((e) => JSON.parse(e));
}
this is a function that takes an array and return the same array but delete every duplicated item
function removeDuplicates(arr) {
return arr.filter((item,
index) => arr.indexOf(item) === index);
}
I didn't understant the part written in spanish so I hope this is what you are looking for
This is a solution specific to your question. this is not a generic solution.
const data = [
{
atributos: {
Tallas: [
{ id: 0, name: "XS" },
{ id: 1, name: "S" },
],
},
},
{
atributos: {
Calzado: [
{ id: 0, name: "10" },
{ id: 1, name: "9.5" },
],
},
},
{
atributos: {
Tallas: [
{ id: 0, name: "XS" },
{ id: 1, name: "S" },
],
},
},
];
function uniqueArray(array) {
const resultObject = array.reduce((acc, eachValue) => {
let keys = Object.keys(eachValue.atributos);
keys.forEach((eachKey) => {
if (!acc[eachKey]) {
acc[eachKey] = [];
}
let list = eachValue["atributos"][eachKey].map(
(each) => each.id + "-" + each.name
);
acc[eachKey].push(...list);
});
return acc;
}, {});
const resultArray = Object.keys(resultObject).reduce((acc, each) => {
let setData = Array.from(new Set(resultObject[each]));
acc.push({
atributos: {
[each]: setData.map((e) => {
return { id: e.split("-")[0], name: e.split("-")[1] };
}),
},
});
return acc;
}, []);
return resultArray;
}
const result = uniqueArray(data)
console.log("result ", JSON.stringify(result, null, 2));

Removing not matching obj from old array and replace matching obj from new array with old matching obj

I cant figure out how to do this...
const arr1 = [{ name: 'peter' }, { name: 'sam', id: 1 }, { name: 'mark' }];
const arr2 = [{ name: 'sam' }, { name: 't' }, { name: 'george' }];
Desired outcome:
const arr2 = [{ name: 'sam', id: 1 }, { name: 't' }, { name: 'george' }];
If you want the previous item I would do this:
const arr1 = [{
name: 'peter'
}, {
name: 'sam',
id: 1
}, {
name: 'mark'
}];
const arr2 = [{
name: 'sam'
}, {
name: 't'
}, {
name: 'george'
}];
const result = arr2.map(item => {
const previousItem = arr1.find(i => i.name === item.name)
if (previousItem) {
return previousItem
}
return item
})
console.log(result);
However, if you want to combine the old and new data, I would recommend spreading the data together, like so:
const arr1 = [{
name: 'peter'
}, {
name: 'sam',
id: 1
}, {
name: 'mark'
}];
const arr2 = [{
name: 'sam'
}, {
name: 't'
}, {
name: 'george'
}];
const result = arr2.map(item => {
const previousItem = arr1.find(i => i.name === item.name)
if (previousItem) {
return {
...previousItem,
...item
}
}
return item
})
console.log(result);
Both allude to the same result here, but you would get different results if arr2's "Sam" object had an additional key "age" on it...
In this example, the second snippet would keep the "age" key because the spread (...) operation combines the two objects together.
You can try this.
const arr1 = [{ name: 'peter' }, { name: 'sam', id: 1 }, { name: 'mark' }];
const arr2 = [{ name: 'sam' }, { name: 't' }, { name: 'george' }];
const result = [];
const res1 = arr2.map((item, i) => {
let index = arr1.findIndex((x) => x.name === item.name);
if ( index > -1 )
result.push(arr1[index]);
else
result.push(item);
})
console.log(result);

How to merge two array of objects by key AND keep unique keys in a single array of objects?

I want to merge two array of objects where objects with the same ID will merge properties and objects with unique IDs will be its own object in the merged array. The following code does the first part where similar IDs will merge but how do I keep objects with unique ids from arr2 in the merged array and have it work with arrays of varying lengths?
Expected output:
[
{
"id": "1",
"date": "2017-01-24",
"name": "test"
},
{
"id": "2",
"date": "2017-01-22",
"bar": "foo"
}
{ "id": "3",
"foo": "bar",
}
]
The code:
let arr1 = [{
id: '1',
createdDate: '2017-01-24'
},
{
id: '2',
createdDate: '2017-01-22'
},
];
let arr2 = [{
id: '1',
name: 'test'
},
{
id: '3',
foo: 'bar'
},
{
id: '2',
bar: 'foo'
},
];
let merged = [];
for (let i = 0; i < arr1.length; i++) {
merged.push({
...arr1[i],
...arr2.find((itmInner) => itmInner.id === arr1[i].id),
},
);
}
console.log(merged);
Iterate over the larger array, the one that contains the smaller array, instead:
let arr1=[{id:"1",createdDate:"2017-01-24"},{id:"2",createdDate:"2017-01-22"}],arr2=[{id:"1",name:"test"},{id:"3",foo:"bar"},{id:"2",bar:"foo"}];
const merged = arr2.map(item => ({
...arr1.find(({ id }) => id === item.id),
...item
}));
console.log(merged);
(if order matters, you can sort if afterwards too)
If you don't know in advance which one / if one will contain the other, then use an object to index the merged objects by IDs first:
let arr1=[{id:"1",createdDate:"2017-01-24"},{id:"2",createdDate:"2017-01-22"}],arr2=[{id:"1",name:"test"},{id:"3",foo:"bar"},{id:"2",bar:"foo"}];
const resultObj = Object.fromEntries(
arr1.map(
item => [item.id, { ...item }]
)
);
for (const item of arr2) {
if (!resultObj[item.id]) {
resultObj[item.id] = item;
} else {
Object.assign(resultObj[item.id], item);
}
}
const merged = Object.values(resultObj);
console.log(merged);
You can create new object that contains the elems of arr1 and arr2 group by id key as follows and the merged array will be stored on object values.
You can get object values using Object.values func.
let arr1 = [{
id: '1',
createdDate: '2017-01-24'
},
{
id: '2',
createdDate: '2017-01-22'
},
];
let arr2 = [{
id: '1',
name: 'test'
},
{
id: '3',
foo: 'bar'
},
{
id: '2',
bar: 'foo'
},
];
const groupById = {};
for (let i = 0; i < Math.min(arr1.length, arr2.length); i ++) {
if (arr1[i]) {
groupById[arr1[i].id] = { ...groupById[arr1[i].id], ...arr1[i] };
}
if (arr2[i]) {
groupById[arr2[i].id] = { ...groupById[arr2[i].id], ...arr2[i] };
}
}
const merged = Object.values(groupById);
console.log(merged);
You could take a single loop approach by storing the objects in a hash table, sorted by id.
const
mergeTo = (target, objects = {}) => o => {
if (!objects[o.id]) target.push(objects[o.id] = {});
Object.assign(objects[o.id], o);
},
array1 = [{ id: '1', createdDate: '2017-01-24' }, { id: '2', createdDate: '2017-01-22' }],
array2 = [{ id: '1', name: 'test' }, { id: '3', foo: 'bar' }, { id: '2', bar: 'foo' }],
merged = [],
merge = mergeTo(merged);
array1.forEach(merge);
array2.forEach(merge);
console.log(merged);
.as-console-wrapper { max-height: 100% !important; top: 0; }
A different approach could be merged the two array as is, and then "squash" it:
let arr1 = [{
id: '1',
createdDate: '2017-01-24'
},
{
id: '2',
createdDate: '2017-01-22'
},
];
let arr2 = [{
id: '1',
name: 'test'
},
{
id: '3',
foo: 'bar'
},
{
id: '2',
bar: 'foo'
},
];
let merged = [...arr1, ...arr2].reduce(
(acc, {id, ...props}) =>
(acc.set(id, {...(acc.get(id) || {}), ...props}), acc), new Map());
console.log([...merged].map( ([id, props]) => ({id, ...props}) ))
Notice that you might not need the last line, it used just to obtain the format you want to, since the above reduce is using a Map as accumulator, you can already access to everything with just merged.get("1").createdDate for example (where "1" is the id).
Since you're operating on one array by merging them at the beginning, you don't care about the length of them or even which one contains more elements. You can also have several arrays instead of just two, it doesn't matter.
What it matters is the order: if more than one array contains the same property for the same "id", the value you'll get is the value from the most recent array added (in the example above, would be arr2).
You can write a function to reduce the arrays to an object and then extract the value from that object which will return the values that you want. You can see the code below:
let arr1 = [
{
id: '1',
createdDate: '2017-01-24',
},
{
id: '2',
createdDate: '2017-01-22',
},
];
let arr2 = [
{
id: '1',
name: 'test',
},
{
id: '3',
foo: 'bar',
},
{
id: '2',
bar: 'foo',
},
];
function merge(arr1 = [], arr2 = []) {
return Object.values(
arr1.concat(arr2).reduce(
(acc, curr) => ({
...acc,
[curr.id]: { ...(acc[curr.id] ?? {}), ...curr },
}),
{}
)
);
}
const merged = merge(arr1, arr2);
Output:
[
{
"id": "1",
"createdDate": "2017-01-24",
"name": "test"
},
{
"id": "2",
"createdDate": "2017-01-22",
"bar": "foo"
},
{
"id": "3",
"foo": "bar"
}
]

How to find a object in a nested array using recursion in JS

Consider the following deeply nested array:
const array = [
{
id: 1,
name: "bla",
children: [
{
id: 23,
name: "bla",
children: [{ id: 88, name: "bla" }, { id: 99, name: "bla" }]
},
{ id: 43, name: "bla" },
{
id: 45,
name: "bla",
children: [{ id: 43, name: "bla" }, { id: 46, name: "bla" }]
}
]
},
{
id: 12,
name: "bla",
children: [
{
id: 232,
name: "bla",
children: [{ id: 848, name: "bla" }, { id: 959, name: "bla" }]
},
{ id: 433, name: "bla" },
{
id: 445,
name: "bla",
children: [
{ id: 443, name: "bla" },
{
id: 456,
name: "bla",
children: [
{
id: 97,
name: "bla"
},
{
id: 56,
name: "bla"
}
]
}
]
}
]
},
{
id: 15,
name: "bla",
children: [
{
id: 263,
name: "bla",
children: [{ id: 868, name: "bla" }, { id: 979, name: "bla" }]
},
{ id: 483, name: "bla" },
{
id: 445,
name: "bla",
children: [{ id: 423, name: "bla" }, { id: 436, name: "bla" }]
}
]
}
];
How would I grab a certain object by key that might be deeply nested, using recursion?
I have tried this, but this won't work for nesting deeper than 2 levels, it then just returns undefined:
const findItemNested = (arr, itemId, nestingKey) => {
for (const i of arr) {
console.log(i.id);
if (i.id === itemId) {
return i;
}
if (i[nestingKey]) {
findItemNested(i[nestingKey], itemId, nestingKey);
}
}
};
The result should be:
const res = findItemNested(array, 959, "children"); >> { id: 959, name: "bla" }
This can perhaps also be achieved using .find, or just to flatten the array (by the children key), but using recursion seems like the most logical solution to me. Does anybody have a solution to this?
Thanks in advance :).
You might use a recursive reduce:
const array=[{id:1,name:"bla",children:[{id:23,name:"bla",children:[{id:88,name:"bla"},{id:99,name:"bla"}]},{id:43,name:"bla"},{id:45,name:"bla",children:[{id:43,name:"bla"},{id:46,name:"bla"}]}]},{id:12,name:"bla",children:[{id:232,name:"bla",children:[{id:848,name:"bla"},{id:959,name:"bla"}]},{id:433,name:"bla"},{id:445,name:"bla",children:[{id:443,name:"bla"},{id:456,name:"bla",children:[{id:97,name:"bla"},{id:56,name:"bla"}]}]}]},{id:15,name:"bla",children:[{id:263,name:"bla",children:[{id:868,name:"bla"},{id:979,name:"bla"}]},{id:483,name:"bla"},{id:445,name:"bla",children:[{id:423,name:"bla"},{id:436,name:"bla"}]}]}];
const findItemNested = (arr, itemId, nestingKey) => (
arr.reduce((a, item) => {
if (a) return a;
if (item.id === itemId) return item;
if (item[nestingKey]) return findItemNested(item[nestingKey], itemId, nestingKey)
}, null)
);
const res = findItemNested(array, 959, "children");
console.log(res);
This should work:
function findByIdRecursive(array, id) {
for (let index = 0; index < array.length; index++) {
const element = array[index];
if (element.id === id) {
return element;
} else {
if (element.children) {
const found = findByIdRecursive(element.children, id);
if (found) {
return found;
}
}
}
}
}
You might also use recursion with Array.find like below
const array=[{id:1,name:"bla",children:[{id:23,name:"bla",children:[{id:88,name:"bla"},{id:99,name:"bla"}]},{id:43,name:"bla"},{id:45,name:"bla",children:[{id:43,name:"bla"},{id:46,name:"bla"}]}]},{id:12,name:"bla",children:[{id:232,name:"bla",children:[{id:848,name:"bla"},{id:959,name:"bla"}]},{id:433,name:"bla"},{id:445,name:"bla",children:[{id:443,name:"bla"},{id:456,name:"bla",children:[{id:97,name:"bla"},{id:56,name:"bla"}]}]}]},{id:15,name:"bla",children:[{id:263,name:"bla",children:[{id:868,name:"bla"},{id:979,name:"bla"}]},{id:483,name:"bla"},{id:445,name:"bla",children:[{id:423,name:"bla"},{id:436,name:"bla"}]}]}];
function findById(arr, id, nestingKey) {
// if empty array then return
if(arr.length == 0) return
// return element if found else collect all children(or other nestedKey) array and run this function
return arr.find(d => d.id == id)
|| findById(arr.flatMap(d => d[nestingKey] || []), id)
|| 'Not found'
}
console.log(findById(array, 12, 'children'))
console.log(findById(array, 483, 'children'))
console.log(findById(array, 1200, 'children'))
We use object-scan for most of our data processing. It's awesome for all sorts of things, but does take a while to wrap your head around. This is how one could answer your question:
// const objectScan = require('object-scan');
const find = (data, id) => objectScan(['**(^children$).id'], {
abort: true,
rtn: 'parent',
useArraySelector: false,
filterFn: ({ value }) => value === id
})(data);
const array=[{id:1,name:"bla",children:[{id:23,name:"bla",children:[{id:88,name:"bla"},{id:99,name:"bla"}]},{id:43,name:"bla"},{id:45,name:"bla",children:[{id:43,name:"bla"},{id:46,name:"bla"}]}]},{id:12,name:"bla",children:[{id:232,name:"bla",children:[{id:848,name:"bla"},{id:959,name:"bla"}]},{id:433,name:"bla"},{id:445,name:"bla",children:[{id:443,name:"bla"},{id:456,name:"bla",children:[{id:97,name:"bla"},{id:56,name:"bla"}]}]}]},{id:15,name:"bla",children:[{id:263,name:"bla",children:[{id:868,name:"bla"},{id:979,name:"bla"}]},{id:483,name:"bla"},{id:445,name:"bla",children:[{id:423,name:"bla"},{id:436,name:"bla"}]}]}];
console.log(find(array, 12));
// => { id: 12, name: 'bla', children: [ { id: 232, name: 'bla', children: [ { id: 848, name: 'bla' }, { id: 959, name: 'bla' } ] }, { id: 433, name: 'bla' }, { id: 445, name: 'bla', children: [ { id: 443, name: 'bla' }, { id: 456, name: 'bla', children: [ { id: 97, name: 'bla' }, { id: 56, name: 'bla' } ] } ] } ] }
console.log(find(array, 483));
// => { id: 483, name: 'bla' }
console.log(find(array, 959));
// => { id: 959, name: 'bla' }
console.log(find(array, 1200));
// => undefined
.as-console-wrapper {max-height: 100% !important; top: 0}
<script src="https://bundle.run/object-scan#13.7.1"></script>
Disclaimer: I'm the author of object-scan
You can do:
const array=[{id:1,name:"bla",children:[{id:23,name:"bla",children:[{id:88,name:"bla"},{id:99,name:"bla"}]},{id:43,name:"bla"},{id:45,name:"bla",children:[{id:43,name:"bla"},{id:46,name:"bla"}]}]},{id:12,name:"bla",children:[{id:232,name:"bla",children:[{id:848,name:"bla"},{id:959,name:"bla"}]},{id:433,name:"bla"},{id:445,name:"bla",children:[{id:443,name:"bla"},{id:456,name:"bla",children:[{id:97,name:"bla"},{id:56,name:"bla"}]}]}]},{id:15,name:"bla",children:[{id:263,name:"bla",children:[{id:868,name:"bla"},{id:979,name:"bla"}]},{id:483,name:"bla"},{id:445,name:"bla",children:[{id:423,name:"bla"},{id:436,name:"bla"}]}]}];
const findItemNested = (arr, itemId, nestingKey) => arr.reduce((a, c) => {
return a.length
? a
: c.id === itemId
? a.concat(c)
: c[nestingKey]
? a.concat(findItemNested(c[nestingKey], itemId, nestingKey))
: a
}, []);
const res = findItemNested(array, 959, "children");
if (res.length) {
console.log(res[0]);
}
This will use recursive find by level, it'll try to find the item in array and then call itself with the children of each item in the array:
New browsers will have Array.prototype.flatten but in this case I've added the flatten function separately.
const array = [{"id":1,"name":"bla","children":[{"id":23,"name":"bla","children":[{"id":88,"name":"bla"},{"id":99,"name":"bla"}]},{"id":43,"name":"bla"},{"id":45,"name":"bla","children":[{"id":43,"name":"bla"},{"id":46,"name":"bla"}]}]},{"id":12,"name":"bla","children":[{"id":232,"name":"bla","children":[{"id":848,"name":"bla"},{"id":959,"name":"bla"}]},{"id":433,"name":"bla"},{"id":445,"name":"bla","children":[{"id":443,"name":"bla"},{"id":456,"name":"bla","children":[{"id":97,"name":"bla"},{"id":56,"name":"bla"}]}]}]},{"id":15,"name":"bla","children":[{"id":263,"name":"bla","children":[{"id":868,"name":"bla"},{"id":979,"name":"bla"}]},{"id":483,"name":"bla"},{"id":445,"name":"bla","children":[{"id":423,"name":"bla"},{"id":436,"name":"bla"}]}]}];
const flatten = (arr) =>
arr.reduce((result, item) => result.concat(item), []);
const findBy = (findFunction, subItemsKey) => (array) =>
//array is empty (can be when children of children of children does not exist)
array.length === 0
? undefined //return undefined when array is empty
: array.find(findFunction) || //return item if found
findBy(findFunction, subItemsKey)(//call itself when item is not found
flatten(
//take children from each item and flatten it
//([[child],[child,child]])=>[child,child,child]
array.map((item) => item[subItemsKey] || []),
),
);
const findChildrenById = (array) => (value) =>
findBy((item) => item.id === value, 'children')(array);
const findInArray = findChildrenById(array);
console.log('found', findInArray(99));
console.log('not found', findInArray({}));
You need to iterate through your objects and then need to be parse each object using recursion. Try the answer mentioned here: JavaScript recursive search in JSON object
code:
`function findNode(id, currentNode) {
var i,
currentChild,
result;
if (id == currentNode.id) {
return currentNode;
} else {
// Use a for loop instead of forEach to avoid nested functions
// Otherwise "return" will not work properly
for (i = 0; i < currentNode.children.length; i += 1) {
currentChild = currentNode.children[i];
// Search in the current child
result = findNode(id, currentChild);
// Return the result if the node has been found
if (result !== false) {
return result;
}
}
// The node has not been found and we have no more options
return false;
}
}`

Get list of duplicate objects in an array of objects

I am trying to get duplicate objects within an array of objects. Let's say the object is like below.
values = [
{ id: 10, name: 'someName1' },
{ id: 10, name: 'someName2' },
{ id: 11, name: 'someName3' },
{ id: 12, name: 'someName4' }
];
Duplicate objects should return like below:
duplicate = [
{ id: 10, name: 'someName1' },
{ id: 10, name: 'someName2' }
];
You can use Array#reduce to make a counter lookup table based on the id key, then use Array#filter to remove any items that appeared only once in the lookup table. Time complexity is O(n).
const values = [{id: 10, name: 'someName1'}, {id: 10, name: 'someName2'}, {id: 11, name:'someName3'}, {id: 12, name: 'someName4'}];
const lookup = values.reduce((a, e) => {
a[e.id] = ++a[e.id] || 0;
return a;
}, {});
console.log(values.filter(e => lookup[e.id]));
Let's say you have:
arr = [
{ id:10, name: 'someName1' },
{ id:10, name: 'someName2' },
{ id:11, name: 'someName3' },
{ id:12, name: 'someName4' }
]
So, to get unique items:
unique = arr
.map(e => e['id'])
.map((e, i, final) => final.indexOf(e) === i && i)
.filter(obj=> arr[obj])
.map(e => arr[e]);
Then, result will be
unique = [
{ id:10, name: 'someName1' },
{ id:11, name: 'someName3' },
{ id:12, name: 'someName4' }
]
And, to get duplicate ids:
duplicateIds = arr
.map(e => e['id'])
.map((e, i, final) => final.indexOf(e) !== i && i)
.filter(obj=> arr[obj])
.map(e => arr[e]["id"])
List of IDs will be
duplicateIds = [10]
Thus, to get duplicates objects:
duplicate = arr.filter(obj=> dublicateIds.includes(obj.id));
Now you have it:
duplicate = [
{ id:10, name: 'someName1' },
{ id:10, name: 'someName2' }
]
Thanks https://reactgo.com/removeduplicateobjects/
You haven't clarified whether two objects with different ids, but the same "name" count as a duplicate. I will assume those do not count as a duplicate; in other words, only objects with the same id will count as duplicate.
let ids = {};
let dups = [];
values.forEach((val)=> {
if (ids[val.id]) {
// we have already found this same id
dups.push(val)
} else {
ids[val.id] = true;
}
})
return dups;
With lodash you can solve this with filter and countBy for complexity of O(n):
const data = [{ id: 10,name: 'someName1' }, { id: 10,name: 'someName2' }, { id: 11,name: 'someName3' }, { id: 12,name: 'someName4' } ]
const counts = _.countBy(data, 'id')
console.log(_.filter(data, x => counts[x.id] > 1))
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.10/lodash.min.js"></script>
You could do the same with ES6 like so:
const data = [{ id: 10,name: 'someName1' }, { id: 10,name: 'someName2' }, { id: 11,name: 'someName3' }, { id: 12,name: 'someName4' } ]
const countBy = (d, id) => d.reduce((r,{id},i,a) => (r[id] = a.filter(x => x.id == id).length, r),{})
const counts = countBy(data, 'id')
console.log(data.filter(x => [x.id] > 1))
You can use an array to store unique elements and use filter on values to only return duplicates.
const unique = []
const duplicates = values.filter(o => {
if(unique.find(i => i.id === o.id && i.name === o.name)) {
return true
}
unique.push(o)
return false;
})
With lodash you can use _.groupBy() to group elements by their id. Than _.filter() out groups that have less than two members, and _.flatten() the results:
const values = [{id: 10, name: 'someName1'}, {id: 10, name: 'someName2'}, {id: 11, name:'someName3'}, {id: 12, name: 'someName4'}];
const result = _.flow([
arr => _.groupBy(arr, 'id'), // group elements by id
g => _.filter(g, o => o.length > 1), // remove groups that have less than two members
_.flatten // flatten the results to a single array
])(values);
console.log(result);
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.11/lodash.min.js"></script>
An alternative based in #ggorlen solution with new Map() as accumulator (for better performance) and without unary operator ++ (not advised by default in projects with ESLint).
const values = [{ id: 10, name: "someName1" }, { id: 10, name: "someName2" }, { id: 11, name: "someName3" }, { id: 12, name: "someName4" },];
const lookup = values.reduce((a, e) => {
a.set(e.id, (a.get(e.id) ?? 0) + 1);
return a;
}, new Map());
console.log(values.filter(e => lookup.get(e.id) > 1));
Try this
function checkDuplicateInObject(propertyName, inputArray) {
var seenDuplicate = false,
testObject = {};
inputArray.map(function(item) {
var itemPropertyName = item[propertyName];
if (itemPropertyName in testObject) {
testObject[itemPropertyName].duplicate = true;
item.duplicate = true;
seenDuplicate = true;
}
else {
testObject[itemPropertyName] = item;
delete item.duplicate;
}
});
return seenDuplicate;
}
referred from : http://www.competa.com/blog/lets-find-duplicate-property-values-in-an-array-of-objects-in-javascript/

Categories

Resources