get array of object value and nested array of object value - javascript

I've this nested array of object array:
const items = [
{
id: 1,
name: 'banana',
selected: true,
},
{
id: 2,
subItems: [
{
id: '2a',
name: 'apple',
selected: true,
},
{
id: '2b',
name: 'orange',
selected: false,
},
],
},
{
id: 3,
name: 'watermalon',
selected: true,
},
{
id: 4,
name: 'pear',
selected: false,
},
]
How can I get the ids base on selected property?
I manage to get the first level, I've tried
const selectedItemId = items.map(item => item.selected && item.id).filter(Boolean)
but how can I select the ids which is in the subItems? I expect the result to be [1, '2a', 3]

Flatten the array first. Be careful of using && item.id inside the mapper because that'll mean that falsey IDs (like 0, which is a reasonable starting number in some schemes) will be excluded.
const items=[{id:1,name:"banana",selected:!0},{id:2,subItems:[{id:"2a",name:"apple",selected:!0},{id:"2b",name:"orange",selected:!1}]},{id:3,name:"watermalon",selected:!0},{id:4,name:"pear",selected:!1}];
const output = items
.flatMap(item => [item].concat(item.subItems ?? []))
.filter(item => item.selected)
.map(item => item.id);
console.log(output);

You can recursively traverse all the items and select the items that have selected set to true.
const items = [
{ id: 1, name: "banana", selected: true },
{
id: 2,
subItems: [
{ id: "2a", name: "apple", selected: true },
{ id: "2b", name: "orange", selected: false },
],
},
{ id: 3, name: "watermalon", selected: true },
{ id: 4, name: "pear", selected: false },
];
function getSelectedItems(items, selectedItems = []) {
for (let item of items) {
if (item.subItems) {
getSelectedItems(item.subItems, selectedItems);
} else if (item.selected) {
selectedItems.push(item.id);
}
}
return selectedItems;
}
console.log(getSelectedItems(items));

let newArray = [];
items.forEach(i=>{
if(i.selected){
newArray.push(i.id)
}
if(i.subItems){
i.subItems.forEach(j=>{
if(j.selected){
newArray.push(j.id)
}
})
}
});
so this is bit lengthy. with 2 map loops

You can do:
const items=[{id:1,name:"banana",selected:!0},{id:2,subItems:[{id:"2a",name:"apple",selected:!0},{id:"2b",name:"orange",selected:!1}]},{id:3,name:"watermalon",selected:!0},{id:4,name:"pear",selected:!1}]
const output = items
.reduce((a, c) => [...a, c, ...(c.subItems || [])], [])
.filter(o => o.selected)
.map(({ id }) => id)
console.log(output)

Checking if a subItems array exsist in the item and recusively calling a function to extract selected Items will solve the issue.
function extractSubItems (items){
var selectItemsId = [];
selectItemsId = selectItemsId + items.map(item => {
if (item.selected===true){
return item.id;
}
if (item.subItems){
return extractSubItems(item.subItems);
}
}).filter(Boolean);
return selectItemsId
}

You can use Array#reduce in a nested fashion as follows:
const items = [ { id: 1, name: 'banana', selected: true, }, { id: 2, subItems: [ { id: '2a', name: 'apple', selected: true, }, { id: '2b', name: 'orange', selected: false, }, ], }, { id: 3, name: 'watermalon', selected: true, }, { id: 4, name: 'pear', selected: false, }, ],
output = items
.reduce(
(prev, {id,selected,subItems}) =>
subItems ?
selected ?
[...prev,id,...subItems.reduce( (p, {id:ID,selected:SEL}) => SEL ? [...p,ID] : p, [] )] :
[...prev,...subItems.reduce( (p, {id:ID,selected:SEL}) => SEL ? [...p,ID] : p, [] )] :
selected ?
[...prev,id] :
prev, []
);
console.log( output )

1 - Loop through items array
2 - if there is no subItems array then find the id of the item using condition
3 - if there is a subItems array then loop through that and find the id using condition
const result = []
items.map(item=>{
item.subItems ?
item.subItems.map(sub=>{
sub.selected && result.push(sub.id)
})
: item.selected && result.push(item.id)
})
console.log(result) // [1, "2a", 3]

This also works:
var ids = [
... items.filter(
it => it.selected || (it.subItems && it.subItems.some( sub => sub.selected ))
)
.map( it =>
it.subItems
? it.subItems.filter( it_sub => it_sub.selected ).map( it_sub => it_sub.id )
: [it.id]
)
].flat()

With resursive of subItems :
const items=[
{id:1,name:"banana",selected:!0},
{id:2,subItems:
[
{id:"2a",name:"apple",selected:!0},
{id:"2b",name:"orange",selected:!1},
{id:"2c",subItems:
[
{id:"2c1",name:"apple1",selected:!0},
{id:"2c1",name:"orange1",selected:!1}
]
},
]
},
{id:3,name:"watermalon",selected:!0},
{id:4,name:"pear",selected:!1}
];
const getSubItem = (obj) => {
let result = !obj.hasOwnProperty('subItems') ? [obj] : obj.subItems.reduce((res, item) => {
return res.concat(getSubItem(item))
}, [])
return result.filter(item => item.selected)
}
const result = items.reduce((res, item) => {
let subItem = getSubItem(item)
return res.concat(getSubItem(item))
}, [])
console.log(result)

Related

Merging/grouping objects in ReactJS

I have the following arrays:
[{id:0,name:'Weight',option:'250'},{id:0,name:'Roast',option:'Medium'}]
[{id:0,name:'Weight',option:'250'},{id:0,name:'Roast',option:'Light'}]
I need to merge them in something like:
[{id:0,name:'Weight',options:['250']},{id:0,name:'Roast',options:['Medium','Light']}]
I tried to nest some loops also tried with merge, push and spread operators but I can't solve it
result.forEach((att) => {
let newoptions = [];
console.log('att', att.attributes);
att.attributes.forEach((id, idx) => {
console.log('id', id);
newoptions = [...newoptions, { option: id.option }];
newAttr[idx] = { name: id.name, options: newoptions };
});
});
I recommend you to concat both arrays and then iterate over it. Then reduce the items with Array.prototype.reduce():
const data1 = [{ id: 0, name: "Weight", option: "250" },{ id: 0, name: "Roast", option: "Medium" }];
const data2 = [{ id: 0, name: "Weight", option: "250" },{ id: 0, name: "Roast", option: "Light" }];
const array = [...data1, ...data2]; // concat
const result = array.reduce((o, c) => {
const exist = o.find(item => item.id === c.id && item.name === c.name);
if (!exist) {
const options = array
.filter(item => item.id === c.id && item.name === c.name)
.map(item => item.option);
o.push({ id: c.id, name: c.name, options: Array.from(new Set(options)) });
}
return o;
}, []);
console.log(result);
Use flat and forEach. Build an object with keys as name and aggregate the values.
const process = (...data) => {
const res = {};
data.flat().forEach(({ name, option, id }) => {
res[name] ??= { name, id, options: [] };
!res[name].options.includes(option) && res[name].options.push(option);
});
return Object.values(res);
};
const arr1 = [
{ id: 0, name: "Weight", option: "250" },
{ id: 0, name: "Roast", option: "Medium" },
];
const arr2 = [
{ id: 0, name: "Weight", option: "250" },
{ id: 0, name: "Roast", option: "Light" },
];
console.log(process(arr1, arr2));

How to change the nested array object to object depending on type in javascript

I would like to know how to change nested array object to object depending on key in javascript
I have objects obj1 and obj2, depending on key item type change the object.
function changeObj(obj){
let result = obj.reduce(function (acc, item) {
if(item.items.trim() !== "" && item.key.trim() !== ""){
acc[item.key] = item.items
return acc
}
return acc
}, {});
return result;
}
let result = this.changeObj(obj2)
var obj1 = [
{ id:0, items:["SG","AU"], count: 2, key:"countries"},
{ id:1, items:["finance"], count: 3 key:"info"}
]
var obj2 = [
{ id:0, items: "SG", key: "country"},
{ id:1, items: "details", key: "info"}
]
Expected Output:
// if items key is array
{
fields: {
countries: ["SG","AU",2],
info: ["finance",3]
}
}
//if items key is string
{
fields: {
country: "SG",
info: "details"
}
}
I think the reason your code is not running is because the wrong format of your objects (1 and 2). Your code is okay except the condition because trim() only works on string type so it errors on array. Try this code snippet
function changeObj(obj){
let result = obj.reduce(function (acc, item) {
acc[item.key] = item.items;
return acc;
}, {});
return result;
}
var obj1 = [
{ id:0, items:["SG","AU"], count: 2, key:"countries"},
{ id:1, items:["finance"], count: 3, key:"info"}
]
var obj2 = [
{ id:0, items: "SG", key: "country"},
{ id:1, items: "details", key: "info"}
]
console.log(changeObj(obj1));
const changeObj = obj =>
obj.reduce((acc, item) => {
if (Array.isArray(item.items)) {
acc[item.key] = [...item.items, item.count];
} else {
acc[item.key] = item.items;
}
return acc;
}, {});
var obj1 = [
{ id: 0, items: ['SG', 'AU'], count: 2, key: 'countries' },
{ id: 1, items: ['finance'], count: 3, key: 'info' }
];
var obj2 = [
{ id: 0, items: 'SG', key: 'country' },
{ id: 1, items: 'details', key: 'info' }
];
console.log(changeObj(obj1));
console.log(changeObj(obj2));
or cleaned up even more
const changeObj = obj =>
obj.reduce((acc, { items, key, count }) => {
Array.isArray(items) ? (acc[key] = [...items, count]) : (acc[key] = items);
return acc;
}, {});
var obj1 = [
{ id: 0, items: ['SG', 'AU'], count: 2, key: 'countries' },
{ id: 1, items: ['finance'], count: 3, key: 'info' }
];
var obj2 = [
{ id: 0, items: 'SG', key: 'country' },
{ id: 1, items: 'details', key: 'info' }
];
console.log(changeObj(obj1));
console.log(changeObj(obj2));

How to compare two array with object?

I compare id with two array with object.
Here is my function:
array1 = [
{ id: 1 },
{ id: 2 },
{ id: 3 }
];
array2 = [
{ id: 1 },
{ id: 2 },
{ id: 3 }
];
const compareFunction = (array1, array2) => {
array2.map((allValue) => {
array1.map((value) => {
allValue.selected = value.id === allValue.id;
});
})
return array2;
}
I think I will get the array2 like
[{ id: 1, selected: true }, { id: 2, selected: true },{ id: 3, selected: true }]
but actually array2 become
[{ id: 1, selected: false }, { id: 2, selected: false },{ id: 3, selected: true }]
Only the last array argument selected become true.
Which step was wrong ? Thanks.
Convert the 2nd array to a Set of id values. Iterate the 1st array with a Array.map() and create a new object for each item, by spreading the current object, and adding the selected value. To get the selected value check if the Set contains that current item id.
const array1 = [{ id: 1 },{ id: 2 },{ id: 3 }];
const array2 = [{ id: 1 },{ id: 2 },{ id: 3 }];
const a2Set = new Set(array2.map(o => o.id))
const result = array1.map(o => ({ ...o, selected: a2Set.has(o.id) }))
console.log(result)
checkout this :
array1 = [{ id: 1 },{ id: 2 },{ id: 3 }];
array2 = [{ id: 1 },{ id: 2 },{ id: 3 }];
const compareFunction = (array1, array2) => {
const result = [];
array2.forEach(arr2item => {
let selected = false;
for(let arr1item of array1){
selected = arr1item.id === arr2item.id;
if(selected)break;
}
result.push({id : arr2item.id , selected : selected});
});
return result;
}
console.log(compareFunction(array1 , array2));

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