how to find distinct object from two array javascript - javascript

I have tow arrays of object like this :
const array1 = [
{ id: 1, name: 'A' },
{ id: 2, name: 'B' },
{ id: 3, name: 'C' }
]
const array2 = [
{ id: 1, name: 'A' },
{ id: 2, name: 'B' }
]
I want another array from arry1 which contains those objects which are not in array2. like this :
[{ id: 1, name: 'C' }]
I tried this approach : var finalArray = array1.filter(function (obj) { return array2.indexOf(obj) === -1; });
But its not working. Please help me

try this :
const array1 = [
{ id: 1, name: 'A' },
{ id: 2, name: 'B' },
{ id: 3, name: 'C' }
]
const array2 = [
{ id: 1, name: 'A' },
{ id: 2, name: 'B' }
]
const array2Names = array2.map(e => e.name)
const arrayYouWant = array1.filter(e => array2Names.includes(e.name) === false)
The array2Names variable return an array like this : ['A','B']
The includes method allows us to know if the analyzed array contains the element in parentheses.

We can use Array.filter and Array.find to get all the objects in array1, but not in array2.
We use .filter to find all the items in array1 that are not present in array2, using .find.
const array1 = [
{ id: 1, name: 'A' },
{ id: 2, name: 'B' },
{ id: 3, name: 'C' }
]
const array2 = [
{ id: 1, name: 'A' },
{ id: 2, name: 'B' }
]
const diff = array1.filter(x1 => !array2.find(x2 => {
return x1.id === x2.id && x1.name === x2.name;
}));
console.log(diff);

const array1 = [
{ id: 1, name: 'A' },
{ id: 2, name: 'B' },
{ id: 3, name: 'C' }
]
const array2 = [
{ id: 1, name: 'A' },
{ id: 2, name: 'B' }
]
const arr = [... new Set(array1.filter(el => !array2.some(el2 => el2.id == el.id)))];
console.log(arr);

Related

How to groupBy the array of object and concat into single array? [duplicate]

This question already has answers here:
group array of objects by id
(8 answers)
Closed 1 year ago.
I want to group the array of objects based on the key and concat all the grouped objects into a single array. GroupBy based on the id
example,
payload
[
{
id: 1,
name: 'a'
},
{
id: 1,
name: 'b'
},
{
id: 1,
name: 'c'
},
{
id: 2,
name: 'b'
},
{
id: 2,
name: 'c'
}
]
expected response
[
[
{
id: 1,
name: 'a'
},
{
id: 1,
name: 'b'
},
{
id: 1,
name: 'c'
}
],
[
{
id: 2,
name: 'b'
},
{
id: 2,
name: 'c'
}
]
]
All the matched elements are in the same array and all the arrays should be in a single array.
Array.redue will help
const input = [
{ id: 1, name: 'a' },
{ id: 1, name: 'b' },
{ id: 1, name: 'c' },
{ id: 2, name: 'b' },
{ id: 2, name: 'c' }
];
const output = input.reduce((acc, curr) => {
const node = acc.find(item => item.find(x => x.id === curr.id));
node ? node.push(curr) : acc.push([curr]);
return acc;
}, []);
console.log(output)
Extract the ids using Set so you have a unique set of them,
then loop over those ids and filter the original array based on it.
let objects = [
{
id: 1,
name: 'a'
},
{
id: 1,
name: 'b'
},
{
id: 1,
name: 'c'
},
{
id: 2,
name: 'b'
},
{
id: 2,
name: 'c'
}
]
let ids = [...new Set(objects.map(i => i.id))]
let result = ids.map(id => objects.filter(n => id === n.id))
console.log(result)
you can create a object with ids array by using Array.reduce method, and get the object values by Object.values
var s = [{
id: 1,
name: 'a'
},
{
id: 1,
name: 'b'
},
{
id: 1,
name: 'c'
},
{
id: 2,
name: 'b'
},
{
id: 2,
name: 'c'
}
];
//go through the input array and create a object with id's, group the values to gather
var ids = s.reduce((a, c) => {
//check object has the `id` property, if not create a property and assign empty array
if (!a[c.id])
a[c.id] = [];
//push the value into desidred object property
a[c.id].push(c)
//return the accumulator
return a;
}, {});
//get the grouped array as values
var outPut = Object.values(ids);
console.log(outPut);
1) You can easily achieve the result using Map and forEach easily
const arr = [
{
id: 1,
name: "a",
},
{
id: 1,
name: "b",
},
{
id: 1,
name: "c",
},
{
id: 2,
name: "b",
},
{
id: 2,
name: "c",
},
];
const map = new Map();
arr.forEach((o) => !map.has(o.id) ? map.set(o.id, [o]) : map.get(o.id).push(o));
const result = [...map.values()];
console.log(result);
/* This is not a part of answer. It is just to give the output full height. So IGNORE IT */
.as-console-wrapper { max-height: 100% !important; top: 0; }
2) You can also achieve the result using reduce
const arr = [
{
id: 1,
name: "a",
},
{
id: 1,
name: "b",
},
{
id: 1,
name: "c",
},
{
id: 2,
name: "b",
},
{
id: 2,
name: "c",
},
];
const result = [...arr.reduce((map, curr) => {
!map.has(curr.id) ? map.set(curr.id, [curr]) : map.get(curr.id).push(curr);
return map;
}, new Map()).values()];
console.log(result);
/* This is not a part of answer. It is just to give the output full height. So IGNORE IT */
.as-console-wrapper { max-height: 100% !important; top: 0; }

Filter object of array by array length

I am trying to sort object of arrays by arrays length, for example, i try to get from this object array where length more than 3
{
friend: [
{ id: 0, name: 'A' },
{ id: 1, name: 'V' },
{ id: 2, name: 'C' },
{ id: 3, name: 'D' }
],
people: [ { id: 0, name: 'A' }, { id: 1, name: 'B' } ]
}
and the result will array friend. I try to do this
function getPart (obj) {
for (let key in obj) {
if (obj[key].length>=4) {
console.log(obj[key]);
}
}}
but I want to try to do it with filter object but I have no idea how to make it
We can achieve that using Object.entries() and reduce() function.
Here's an example:
JS
let data = {
friend: [
{ id: 0, name: 'A' },
{ id: 1, name: 'V' },
{ id: 2, name: 'C' },
{ id: 3, name: 'D' }
],
people: [ { id: 0, name: 'A' }, { id: 1, name: 'B' } ]
}
// Convert first the object to an array using Object.entries so we can loop it using reduce() function
// Then we make a condition statement if the object's length is >= 4, then we'll filter that to the new object.
let new_data = Object.entries(data).reduce((a, b) => a = {...a, ...(b[1].length >= 4 ? {[b[0]]: b[1]} : {})} ,{})
console.log(new_data) // Expected result: { friend: [Object] }
Just one line:
Object.values(obj).filter(ob => ob.length >= 4);
const ob = {
friend: [
{ id: 0, name: 'A' },
{ id: 1, name: 'V' },
{ id: 2, name: 'C' },
{ id: 3, name: 'D' }
],
people: [ { id: 0, name: 'A' }, { id: 1, name: 'B' } ]
}
function getPart (obj) {
const filtered = Object.values(obj).filter(ob => ob.length >= 4);
console.log(filtered);
}
getPart(ob);

compare two arrays in javascript and delete the object that both arrays have

I have 2 arrays:
0: {id: 2, name: "TMA"}
1: {id: 3, name: "Hibbernate"}
0: {id: 1, name: "FB.DE"}
1: {id: 2, name: "TMA"}
2: {id: 3, name: "Hibbernate"}
3: {id: 4, name: "Event.it A"}
4: {id: 5, name: "Projket 2"}
5: {id: 6, name: "Projekt 1"}
I want to compare them and delete the objects with the id 2 and 3 cause both arrays have them and thats the similarity.
This is my Code so far:
const projectListOutput = projectsOfPersonArray.filter(project => data.includes(project));
console.log(projectListOutput);
But every time i run this projectListOutput is empty.
When using includes dont compare objects, Just build data as array of strings. Remaining code is similar to what you have.
arr1 = [
{ id: 2, name: "TMA" },
{ id: 3, name: "Hibbernate" },
];
arr2 = [
{ id: 1, name: "FB.DE" },
{ id: 2, name: "TMA" },
{ id: 3, name: "Hibbernate" },
{ id: 4, name: "Event.it A" },
{ id: 5, name: "Projket 2" },
{ id: 6, name: "Projekt 1" },
];
const data = arr1.map(({ id }) => id);
const result = arr2.filter(({ id }) => !data.includes(id));
console.log(result);
Your data array probably does not contain the exact same object references than projectsOfPersonArray. Look at the code below:
[{ foo: 'bar' }].includes({ foo: 'bar' });
// false
Objects look equal, but they don't share the same reference (= they're not the same).
It's safer to use includes with primitive values like numbers or strings. You can for example check the ids of your objects instead of the full objects.
You compare different objects, so every object is unique.
For filtering, you need to compare all properties or use a JSON string, if the order of properties is equal.
var exclude = [{ id: 2, name: "TMA" }, { id: 3, name: "Hibbernate" }],
data = [{ id: 2, name: "TMA" }, { id: 3, name: "Hibbernate" }, { id: 1, name: "FB.DE" }, { id: 2, name: "TMA" }, { id: 3, name: "Hibbernate" }, { id: 4, name: "Event.it A" }, { id: 5, name: "Projket 2" }, { id: 6, name: "Projekt 1" }],
result = data.filter(project =>
!exclude.some(item => JSON.stringify(item) === JSON.stringify(project))
);
console.log(result);
.as-console-wrapper { max-height: 100% !important; top: 0; }
You can do something similar to the next:
const source = [{
id: 1,
name: "FB.DE"
},
{
id: 2,
name: "TMA"
},
{
id: 3,
name: "Hibbernate"
},
{
id: 4,
name: "Event.it A"
},
{
id: 5,
name: "Projket 2"
},
{
id: 6,
name: "Projekt 1"
}
]
const toRemove = [{
id: 2,
name: "TMA"
},
{
id: 3,
name: "Hibbernate"
}
]
/**create object where keys is object "id" prop, and value is true**/
const toRemoveMap = toRemove.reduce((result, item) => ({
...result,
[item.id]: true
}), {})
const result = source.filter(item => !toRemoveMap[item.id])
You can make function from it:
function removeArrayDuplicates (sourceArray, duplicatesArray, accessor) {
const toRemoveMap = duplicatesArray.reduce((result, item) => ({
...result,
[item[accessor]]: true
}), {});
return sourceArray.filter(item => !toRemoveMap[item[accessor]])
}
removeArrayDuplicates(source, toRemove, 'id')
Or even better, you can make it work with a function instead of just property accessor:
function removeDuplicates (sourceArray, duplicatesArray, accessor) {
let objectSerializer = obj => obj[accessor];
if(typeof accessor === 'function') {
objectSerializer = accessor;
}
const toRemoveMap = duplicatesArray.reduce((result, item) => ({
...result,
[objectSerializer(item)]: true
}), {});
return sourceArray.filter(item => !toRemoveMap[objectSerializer(item)])
}
removeDuplicates(source, toRemove, (obj) => JSON.stringify(obj))
This function will help you merge two sorted arrays
var arr1 = [
{ id: 2, name: 'TMA' },
{ id: 3, name: 'Hibbernate' },
]
var arr2 = [
{ id: 1, name: 'FB.DE' },
{ id: 2, name: 'TMA' },
{ id: 3, name: 'Hibbernate' },
{ id: 4, name: 'Event.it A' },
{ id: 5, name: 'Projket 2' },
]
function mergeArray(array1, array2) {
var result = []
var firstArrayLen = array1.length
var secondArrayLen = array2.length
var i = 0 // index for first array
var j = 0 // index for second array
while (i < firstArrayLen || j < secondArrayLen) {
if (i === firstArrayLen) { // first array doesn't have any other members
while (j < secondArrayLen) { // we copy rest members of first array as a result
result.push(array2[j])
j++
}
} else if (j === secondArrayLen) { // second array doesn't have any other members
while (i < firstArrayLen) { // we copy the rest members of the first array to the result array
result.push(array1[i])
i++
}
} else if (array1[i].id < array2[j].id) {
result.push(array1[i])
i++
} else if (array1[i].id > array2[j].id) {
result.push(array2[j])
j++
} else {
result.push(array1[i])
i++
j++
}
}
return result
}
console.log(mergeArray(arr1,arr2));

filter objects from array that have the same value at given key

Let's say we have an array that looks like this:
[
{
id: 0,
name: 'A'
},
{
id: 1,
name:'A'
},
{
id: 2,
name: 'C'
},
{
id: 3,
name: 'B'
},
{
id: 4,
name: 'B'
}
]
I want to keep only this objects that have the same value at 'name' key. So the output looks like this:
[
{
id: 0,
name: 'A'
},
{
id: 1,
name:'A'
},
{
id: 3,
name: 'B'
},
{
id: 4,
name: 'B'
}
]
I wanted to use lodash but I don't see any method for this case.
You can try something like this:
Idea:
Loop over the data and create a list of names with their count.
Loop over data again and filter out any object that has count < 2
var data = [{ id: 0, name: 'A' }, { id: 1, name: 'A' }, { id: 2, name: 'C' }, { id: 3, name: 'B' }, { id: 4, name: 'B' }];
var countList = data.reduce(function(p, c){
p[c.name] = (p[c.name] || 0) + 1;
return p;
}, {});
var result = data.filter(function(obj){
return countList[obj.name] > 1;
});
console.log(result)
A lodash approach that may (or may not) be easier to follow the steps of:
const originalArray = [{ id: 0, name: 'A' }, { id: 1, name: 'A' }, { id: 2, name: 'C' }, { id: 3, name: 'B' }, { id: 4, name: 'B' }];
const newArray =
_(originalArray)
.groupBy('name') // when names are the same => same group. this gets us an array of groups (arrays)
.filter(group => group.length == 2) // keep only the groups with two items in them
.flatten() // flatten array of arrays down to just one array
.value();
console.log(newArray)
<script src="https://cdn.jsdelivr.net/npm/lodash#4.17.11/lodash.min.js"></script>
A shorter solution with array.filter and array.some:
var data = [ { ... }, ... ]; // Your array
var newData = data.filter((elt, eltIndex) => data.some((sameNameElt, sameNameEltIndex) => sameNameElt.name === elt.name && sameNameEltIndex !== eltIndex));
console.log("new table: ", newTable);
You could use a hash table and a single loop for mapping the objects or just an empty array, then concat the result with an empty array.
var data = [{ id: 0, name: 'A' }, { id: 1, name: 'A' }, { id: 2, name: 'C' }, { id: 3, name: 'B' }, { id: 4, name: 'B' }],
hash = Object.create(null),
result = Array.prototype.concat.apply([], data.map(function (o, i) {
if (hash[o.name]) {
hash[o.name].update && hash[o.name].temp.push(hash[o.name].object);
hash[o.name].update = false;
return o;
}
hash[o.name] = { object: o, temp: [], update: true };
return hash[o.name].temp;
}));
console.log(result);
.as-console-wrapper { max-height: 100% !important; top: 0; }

How to get array of object's propety value in an array

How can we return an array of object's property values?
[
{ id: 1, category: 'A' },
{ id: 2, category: 'A' },
{ id: 3, category: 'C' },
{ id: 4, category: 'B' },
{ id: 5, category: 'A' },
]
I would like to get all the ids with category = 'A' [1, 2, 5] and using .map() include an undefined objects which i don't like and filter returns the entire object and not the id.
Using .map() output: [1, 2, undefined, undefined, 5]
using .filter() output:
[
Object {
category: 'A',
id: 1
},
Object {
category: 'A',
id: 2
},
Object {
category: 'A',
id: 5,
},
]
DEMO
One option is to use Array#filter and then Array#map:
var data = [{"id":1,"category":"A"},{"id":2,"category":"A"},{"id":3,"category":"C"},{"id":4,"category":"B"},{"id":5,"category":"A"}];
var result = data.filter(function(item) {
return item.category === 'A';
}).map(function(item) {
return item.id;
});
console.log(result);
Another option is to use Array#reduce:
var data = [{"id":1,"category":"A"},{"id":2,"category":"A"},{"id":3,"category":"C"},{"id":4,"category":"B"},{"id":5,"category":"A"}];
var result = data.reduce(function(items, item) {
item.category === 'A' && items.push(item.id);
return items;
}, []);
console.log(result);
You could use Array#reduce with a single loop.
var array = [{ id: 1, category: 'A' }, { id: 2, category: 'A' }, { id: 3, category: 'C' }, { id: 4, category: 'B' }, { id: 5, category: 'A' }],
category = 'A',
result = array.reduce(function (r, o) {
if (o.category === category) {
r.push(o.id);
}
return r;
}, []);
console.log(result);
you could combine both filter() and map()
var data = [{ id: 1, category: 'A' }, { id: 2, category: 'A' }, { id: 3, category: 'C' }, { id: 4, category: 'B' }, { id: 5, category: 'A' }]
var new_data_filter = data.filter(function(item) {
if (item.category === 'A') {
return item.id
}
}).map(function(a){return a.id})
console.log(new_data_filter)
For ES6
var new_data_filter = data.filter(item => item.category === 'A').map(a => a.id)

Categories