Comparing objects in two arrays - javascript

I want to compare objects in two arrays and if they are not the same, add them to the array.
first array
[
{
"email": "a#a.com"
},
{
"email": "b#b.com"
},
{
"email": "c#c.com"
},
{
"email": "d#d.com"
}
]
secund array
[
{
"email": "v#v.com"
},
{
"email": "k#k.com"
},
{
"email": "g#g.com"
}
]
checking function
if($scope.participants.length > 0){
result.forEach(function (resultElement) {
if(!$scope.participants.includes(resultElement) ) {
$scope.participants.push(resultElement);
}
})
result = [];
console.log($scope.participants);
}
I checked the debug and it drops on the if condition.

You need to understand that two objects are not equal and the same.
For example {} === {} returns false
if you want to compare objects you need to compare each primitive element of each object.
Primitives include numbers, strings, booleans, etc and not objects or arrays (which are also objects).

b1 = [
{ id: 0, email: 'john#' },
{ id: 1, email: 'mary#' },
{ id: 2, email: 'pablo#' },
{ id: 3, email: 'escobar#' }
];
b2 = [
{ id: 0, email: 'john#' },
{ id: 1, email: 'mary#' }
];
var res = this.b1.filter(item1 =>
!this.b2.some(item2 => (item2.id === item1.id && item2.name === item1.name)))
console.log("check more is working",res);

Related

Populate object key without using mongoose/mongodb

I have this Mongoose Object:
recipe = {
"ingredients": [
{
"_id": "5fc8b729c47c6f38b472078a",
"ingredient": {
"unit": "ml",
"name": "olive oil",
"createdAt": "2020-10-09T10:53:35.567Z",
"updatedAt": "2020-12-03T09:25:43.282Z",
"unitConversion": [
{
"_id": "5fc0a688c1799719d03aea3f",
"value": 20,
"convertedValue": 1,
"unitMeasure": {
"name": "spoon",
"createdAt": "2020-11-19T07:31:11.353Z",
"updatedAt": "2020-11-19T07:31:11.353Z",
"id": "5fb61f3f0a62dc27fc052271"
}
}
],
"id": "5f80412f583af20c8c0aeea1"
},
"quantity": 2,
"unitConv": "5fc0a688c1799719d03aea3f"
}
]
}
What I want to do, populate the unitConv with the object from unitConversion array that has a matching id.
Here is my code:
const newRecipe = recipe.ingredients.map((ingredient) => {
let unit
if (ingredient.unitConv && ingredient.unitConv !== null) {
unit = ingredient.ingredient.unitConversion.reduce((unit) => {
if (unit.id === ingredient.unitConv) {
return unit
}
})
ingredient.unitConv = unit
}
return ingredient
})
It works. ingredient.unitConv gets populated with the object with the matching id from the unitConversion array, but is not an object. It's being added as a string.
This is how ingredient.unitConv is being populated:
"unitConv": "{\n _id: 5fc0a688c1799719d03aea3f,\n value: 20,\n convertedValue: 1,\n unitMeasure: {\n _id: 5fb61f3f0a62dc27fc052271,\n name: 'spoon',\n createdAt: 2020-11-19T07:31:11.353Z,\n updatedAt: 2020-11-19T07:31:11.353Z,\n }\n}"
I tried using JSON.parse() on it, but it won't work, I will get several errors of SyntaxError type (Unexpected token in JSON at position...). I tried JSON.parse(JSON.stringify('the object')), but this won't populate at all.
In your environment it is probably a string, but when passing the code here, it remains as an object. Try to check the data type like this:
recipe = {
ingredients: [
{
_id: '5fc8b729c47c6f38b472078a',
ingredient: {
unit: 'ml',
name: 'olive oil',
createdAt: '2020-10-09T10:53:35.567Z',
updatedAt: '2020-12-03T09:25:43.282Z',
unitConversion: [
{
_id: '5fc0a688c1799719d03aea3f',
value: 20,
convertedValue: 1,
unitMeasure: {
name: 'spoon',
createdAt: '2020-11-19T07:31:11.353Z',
updatedAt: '2020-11-19T07:31:11.353Z',
id: '5fb61f3f0a62dc27fc052271',
},
},
],
id: '5f80412f583af20c8c0aeea1',
},
quantity: 2,
unitConv: '5fc0a688c1799719d03aea3f',
},
],
};
const newRecipe = recipe.ingredients.map((ingredient) => {
let unit;
if (ingredient.unitConv && ingredient.unitConv !== null) {
unit = ingredient.ingredient.unitConversion.reduce((unit) => {
if (unit.id === ingredient.unitConv) {
return unit;
}
});
ingredient.unitConv = unit;
}
return ingredient;
});
console.log(`unitConv is an ${typeof newRecipe[0].unitConv}`);
I would suggest you to user filter function instead of reduce function in your code. In this case you will get a array of objects. Also please check the type of unitConv in your schema.

Create array of objects

myArray = [
{
obj: {
name: "Andy",
phone: ["11111111", "22222222"],
email: ["andy#andy.com"],
},
},
{obj: { name: "Kate", phone: ["073463653"] } },
{obj: { name: "July", email: ["july#gmail.com", "july#bes.com"] } },
];
I've tried something like this, but I can't map through the phone no and get a valid result. If you guys have an idea or some suggestions I would really appreciate it
ngOnInit() {
Object.keys(
this.myArray.map((key) => {
const objectWithData = {
[name]: key._objectReference.name,
phoneNumbers: key._objectReference.phoneNumbers.map((each) => {
phoneNumbers: each;
}),
};
return objectWithData;
})
);
}
As an alternative, I'd prefer to use reduce for something like this with the phone numbers/emails and find it more readable than the nested mapping. Also, I would change the resulting model to strings instead of arrays since you are showing a different model anyway that isn't really lists. You can modify the below to put them in arrays if you need to...
Also, you'll notice the keys are still there for undefined properties. If you want to leave the keys out you'd just have to build up the object conditionally before passing to newArr.push({});
EDIT:
After reviewing the OP I see now that you meant for names to be repeated in the results for each phone/email - and repeating the first element in the shorter array if possible (e.g., andy's one email repeating for each phone number).
The below is the best I can do for this, it works, just does not look all that elegant IMO.
The assumption is that in the case you have more phone numbers than emails or vice versa, you want to repeat the first element of the shorter array in order to always include that contact option in each contact record. Otherwise each contact record would have a phone number and email with matching indexes in the respective arrays.
I first check to determine which array is longer (phone or email) and loop only once through the longer one so you get every contact option in the loop and create contact records in the new array for each element in the longer array.
For the phone and email fields, each ugly expression determines:
-Are there any phone/email options?
-Are there options at the current index (of the longer array loop)?
-If not, is there an element in the first position to use as default?
-Else leave it undefined
function mapContacts(arr) {
var longerArr;
return arr.reduce((newArr, currEle) => {
currEle = currEle.obj;
if (currEle.phone && currEle.phone.length > (currEle.email ? currEle.email.length : 0)) {
longerArr = currEle.phone;
} else if (currEle.email && currEle.email.length > 0) {
longerArr = currEle.email;
} else {
return; // No contact info
}
longerArr.forEach((ele, index) => {
newArr.push({
name: currEle.name,
phone: currEle.phone && (currEle.phone[index] ? currEle.phone[index] :
(currEle.phone[0] && currEle.phone[0])),
email: currEle.email && (currEle.email[index] ? currEle.email[index] :
(currEle.email[0] && currEle.email[0]))
});
});
return newArr;
}, []);
}
var myArray = [
{
obj: {
name: "Andy",
phone: ["11111111", "22222222"],
email: ["andy#andy.com"]
}
},
{ obj: { name: "Kate", phone: ["073463653"] } },
{ obj: { name: "July", email: ["july#gmail.com", "july#bes.com"] } },
{ obj: { name: "Jay", phone: ["489375438"], email: ["jay#gmail.com", "jay#bes.com"] } },
];
var newArr = mapContacts(myArray);
console.log(newArr);
/* Output
[
{
"name": "Andy",
"phone": "11111111",
"email": "andy#andy.com"
},
{
"name": "Andy",
"phone": "22222222",
"email": "andy#andy.com"
},
{
"name": "Kate",
"phone": "073463653",
"email": undefined
},
{
"name": "July",
"phone": undefined,
"email": "july#gmail.com"
},
{
"name": "July",
"phone": undefined,
"email": "july#bes.com"
},
{
"name": "Jay",
"phone": "489375438",
"email": "jay#gmail.com"
},
{
"name": "Jay",
"phone": "489375438",
"email": "jay#bes.com"
}
]
*/
Does it fit an answer for you ?
first answer
const myArray =
[ { _objectReference:
{ name: "Andy"
, phoneNumbers: [ "11111111", "22222222"]
, emails: [ "andy#andy.com"]
}
}
, { _objectReference:
{ name: "Kate"
, phoneNumbers: [ "073463653"]
}
}
, { _objectReference:
{ name: "July"
, emails: [ "july#gmail.com", "july#bes.com"]
}
}
]
const newArrayContacts =
myArray.reduce((a,c)=>
{
let row = c._objectReference
, newEl = { name: row.name }
if (row.phoneNumbers) { newEl.phoneNumber = row.phoneNumbers[0] }
if (row.emails) { newEl.email = row.emails[0] }
if ( row.phoneNumbers
&& row.phoneNumbers.length > 1 )
{
row.phoneNumbers.forEach(phoneNumber =>
{
newEl.phoneNumber = phoneNumber
a.push ( {...newEl } )
})
}
else if (row.emails
&& row.emails.length > 1 )
{
row.emails.forEach(email =>
{
newEl.email = email
a.push ( {...newEl } )
})
}
else
{ a.push ( newEl ) }
return a
},[])
console.log( newArrayContacts )
second answer (Angular ?)
const myArray =
[ { name: "Andy", phoneNumbers: [ "11111111", "22222222"] , emails: [ "andy#andy.com"] }
, { name: "Kate", phoneNumbers: [ "073463653"] }
, { name: "July", emails: [ "july#gmail.com", "july#bes.com"] }
]
const newArrayContacts =
myArray.reduce((acc,row)=>
{
let newEl = { name: row.name }
if (row.phoneNumbers) { newEl.phoneNumber = [row.phoneNumbers[0]] }
if (row.emails) { newEl.email = [row.emails[0]] }
if ( row.phoneNumbers
&& row.phoneNumbers.length > 1 )
{
row.phoneNumbers.forEach((phoneNumber)=>
{
newEl.phoneNumber = [phoneNumber]
acc.push ( {...newEl } )
})
}
else if (row.emails
&& row.emails.length > 1 )
{
row.emails.forEach(email =>
{
newEl.email = [email]
acc.push ( {...newEl } )
})
}
else
{ acc.push ( newEl ) }
return acc
},[])
console.log( JSON.stringify( newArrayContacts,0,2) )
the map function returns nothing
phoneNumbers: key._objectReference.phoneNumbers.map((each) => {
phoneNumbers: each;
}),
you have to return the object
phoneNumbers: key._objectReference.phoneNumbers.map((each) => return {
phoneNumbers: each
}),
or
phoneNumbers: key._objectReference.phoneNumbers.map((each) => ({
phoneNumbers: each
})),
but that doesn't solve your overall problem.
to solve this i don't think you can use only the map function as it returns an array with the same number of elements as the original,
i would use nested for / foreach and build an array as i go

array some is not working in nested array

I want to check if current user is present in nested array or not.
this is few part of my sample array which is getting from API:
[
{
"owner":"abc",
"_id":"xyz77",
"comments":[
],
"likes":[
{
"_id":"9999",
"username":"user1"
},
{
"_id":"9998",
"username":"user2"
}
]
},
{
"owner":"bcd"
}
]
I want to see if user1 is present in likes array or not.
if yes then it should give output like this:
[
{
"owner":"abc",
"user1":true
},
{
"owner":"bcd",
"user1":true
},
{
"owner":"def",
"user1":false
}
]
above result is likes array of owner abc has user1 but not present in owner def.
I tried with array.some for likes array inside forEach of owner array. But not getting proper result.
help is appreciated
You can use a combination of Array.prototype.map and Array.prototype.some to create a resulting array which checks if any of the users in the likes array of each owner object matches your username:
const data = [
{
"owner":"abc",
"_id":"xyz77",
"comments":[],
"likes":[
{
"_id":"9999",
"username":"user1"
},
{
"_id":"9998",
"username":"user2"
}
]
},
{
"owner":"bcd",
"_id":"xyz88",
"comments":[],
"likes":[
{
"_id":"9998",
"username":"user2"
},
{
"_id":"9997",
"username":"user3"
}
]
},
];
const checkUsername = (data, username) => {
return data.map(e => {
const x = { owner: e.owner };
x[username] = e.likes.some(el => el.username === username);
return x;
});
};
console.log(checkUsername(data, 'user1'));
console.log(checkUsername(data, 'user2'));
Its Similar to #awarrier99 answer, Use destructuring along with map and some.
const data = [
{
owner: "abc",
_id: "xyz77",
comments: [],
likes: [
{
_id: "9999",
username: "user1",
},
{
_id: "9998",
username: "user2",
},
],
},
{
owner: "bcd",
},
];
const update = (arr, user) =>
data.map(({ likes = [], owner }) => ({
[user]: likes.some(({ username }) => username === user),
owner,
}));
console.log(update(data, "user1"));

Delete duplicate elements from Array in Javascript [duplicate]

This question already has answers here:
How to get distinct values from an array of objects in JavaScript?
(63 answers)
Get all unique values in a JavaScript array (remove duplicates)
(91 answers)
Closed 6 years ago.
I have array with obejcts email and Id so I want delete duplicate elements who have similar ID's.
Example:
var newarray=[
{
Email:"test1#gmail.com",
ID:"A"
},
{
Email:"test2#gmail.com",
ID:"B"
},
{
Email:"test3#gmail.com",
ID:"A"
},
{
Email:"test4#gmail.com",
ID:"C"
},
{
Email:"test4#gmail.com",
ID:"C"
}
];
Now I need to delete Duplicate elements which have ID's are common.In the sence I am expecting final Array is
var FinalArray=[
{
Email:"test1#gmail.com",
ID:"A"
},
{
Email:"test2#gmail.com",
ID:"B"
},
{
Email:"test5#gmail.com",
ID:"C"
}
];
Use Array.prototype.filter to filter out the elements and to keep a check of duplicates use a temp array
var newarray = [{
Email: "test1#gmail.com",
ID: "A"
}, {
Email: "test2#gmail.com",
ID: "B"
}, {
Email: "test3#gmail.com",
ID: "A"
}, {
Email: "test4#gmail.com",
ID: "C"
}, {
Email: "test5#gmail.com",
ID: "C"
}];
// Array to keep track of duplicates
var dups = [];
var arr = newarray.filter(function(el) {
// If it is not a duplicate, return true
if (dups.indexOf(el.ID) == -1) {
dups.push(el.ID);
return true;
}
return false;
});
console.log(arr);
You could filter it with a hash table.
var newarray = [{ Email: "test1#gmail.com", ID: "A" }, { Email: "test2#gmail.com", ID: "B" }, { Email: "test3#gmail.com", ID: "A" }, { Email: "test4#gmail.com", ID: "C" }, { Email: "test5#gmail.com", ID: "C" }],
filtered = newarray.filter(function (a) {
if (!this[a.ID]) {
this[a.ID] = true;
return true;
}
}, Object.create(null));
console.log(filtered);
.as-console-wrapper { max-height: 100% !important; top: 0; }
ES6 with Set
var newarray = [{ Email: "test1#gmail.com", ID: "A" }, { Email: "test2#gmail.com", ID: "B" }, { Email: "test3#gmail.com", ID: "A" }, { Email: "test4#gmail.com", ID: "C" }, { Email: "test5#gmail.com", ID: "C" }],
filtered = newarray.filter((s => a => !s.has(a.ID) && s.add(a.ID))(new Set));
console.log(filtered);
.as-console-wrapper { max-height: 100% !important; top: 0; }
If you can use Javascript libraries such as underscore or lodash, I recommend having a look at _.uniq function in their libraries. From lodash:
_.uniq(array, [isSorted=false], [callback=_.identity], [thisArg])
Here you have to use like below,
var non_duplidated_data = _.uniq(newarray, 'ID');
Another solution using Array.prototype.reduce and a hash table - see demo below:
var newarray=[ { Email:"test1#gmail.com", ID:"A" }, { Email:"test2#gmail.com", ID:"B" }, { Email:"test3#gmail.com", ID:"A" }, { Email:"test4#gmail.com", ID:"C" }, { Email:"test5#gmail.com", ID:"C" } ];
var result = newarray.reduce(function(hash){
return function(prev,curr){
!hash[curr.ID] && (hash[curr.ID]=prev.push(curr));
return prev;
};
}(Object.create(null)),[]);
console.log(result);
.as-console-wrapper{top:0;max-height:100%!important;}

how to split array of objects into multiple array of objects by subvalue

I need to split an Array by its objects subvalue (type).
Let's assume I have following array:
[
{id:1,name:"John",information: { type :"employee"}},
{id:2,name:"Charles",information: { type :"employee"}},
{id:3,name:"Emma",information: { type :"ceo"}},
{id:4,name:"Jane",information: { type :"customer"}}
]
and I want to split the object by information.type so my final result looks like:
[
{
type:"employee",
persons:
[
{id:1,name:"John",information: { ... }},
{id:2,name:"Charles",information: { ... }
]
},
{
type:"ceo",
persons:
[
{id:3,name:"Emma",information: { ... }}
]
},
{
type:"customer",
persons:
[
{id:4,name:"Jane",information: { ... }}
]
},
]
Underscore is available at my Project. Any other helper library could be included.
Of course I could loop through the array and implement my own logic, but i was looking for cleaner solution.
This returns exactly what you want:
_.pairs(_.groupBy(originalArray, v => v.information.type)).map(p => ({type: p[0], persons: p[1]}))
A solution in plain Javascript with a temporary object for the groups.
var array = [{ id: 1, name: "John", information: { type: "employee" } }, { id: 2, name: "Charles", information: { type: "employee" } }, { id: 3, name: "Emma", information: { type: "ceo" } }, { id: 4, name: "Jane", information: { type: "customer" } }],
result = [];
array.forEach(function (a) {
var type = a.information.type;
if (!this[type]) {
this[type] = { type: type, persons: [] };
result.push(this[type]);
}
this[type].persons.push({ id: a.id, name: a.name });
}, {});
document.write('<pre>' + JSON.stringify(result, 0, 4) + '</pre>');
You could use the groupBy function of underscore.js:
var empList = [
{id:1,name:"John",information: { type :"employee"}},
{id:2,name:"Charles",information: { type :"employee"}},
{id:3,name:"Emma",information: { type :"ceo"}},
{id:4,name:"Jane",information: { type :"customer"}}
];
_.groupBy(empList, function(emp){ return emp.information.type; });

Categories