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
Related
let student = [{
id:1,
name:'aman',
class:'10',
gender:'male'
},{
id:2,
name:'shivani',
class:'10',
gender:'female'
},{
id:2,
name:'riyan',
class:'11',
gender:'female'
}]
function customFilter(objList, text){
if(undefined === text || text === '' ) return objList;
return objList.filter(product => {
let flag;
for(let prop in product){
if(product[prop].toString().indexOf(text)>-1){
product[prop] = 0
product[prop]++
flag = product[prop]
console.log(flag)
}
}
return flag;
});}
console.log( customFilter(student, '10'))
I want the output of the number of students in a class. Example: when I pass class 10 as an argument then i should get output how many students in class 10
output:
{class:10,stduent:5 }
I didn't get your question well, but I assumed you want number of student in a class like this {class:10, students: 2}
let student = [
{ id:1, name:'aman', class:'10', gender:'male'},
{ id:2, name:'shivani', class:'10', gender:'female' },
{ id:3, name:'riyan', class:'11', gender:'female' }
]
function customFilter(objList, text){
if(undefined === text || text === '' ) return objList;
const numberOfStudents = objList.filter(product => {
for (let prop in product) {
if (product[prop].toString().includes(text)) {
return true;
}
}
});
return {class:text, student:numberOfStudents.length }
}
console.log( customFilter(student, '10'))
If that's the case this code will do , hope it helps
This would also work:
let students = [
{ id: 1, name: "aman", class: "10", gender: "male" },
{ id: 2, name: "shivani", class: "10", gender: "female" },
{ id: 2, name: "riyan", class: "11", gender: "female" },
];
const customFilter = (students, key, value) => {
const res = { [key]: value, student: 0 };
students.forEach((student) => {
if (student[key] === value) {
res.student += 1;
}
});
return res;
};
console.log(customFilter(students, "class", "10"));
Using Array.prototype.forEach()
There are few problems with the code. change class:'10' to grade: 10,.
don't use "class" as a variable name. might cause a few errors
There is a missing ,
numbers shouldn't be inside quotes because the number will be stored as a string
let student = [
{ id: 1, name: 'aman', grade: 10, gender: 'male'},
{ id: 2, name: 'shivani', grade: 10, gender: 'female' },
{ id: 2, name: 'riyan', grade: 11, gender: 'female' },
]
function customFilter(objList, value){
if(!value || value === '') return objList;
let count = 0
objList.forEach(obj => {
const { grade } = obj;
if(grade === value){
count++;
}
})
return {grade: 10, count};
}
console.log(customFilter(student, 10));
and forEach can be used instead of filter. It loops from start to end of an array
Use .reduce() to group all objects that match.
/* hits (accumulator) is initially an empty array.
now (current) is the object of the current iteration. */
array.reduce((hits, now) => { //...
On each iteration, get all of the current object's values (in lower case) in an array.
Object.values(now).map(val => val.toLowerCase())
/* result of the first object: ["01gn3z1ryjjqhn588ax3bws6qb", "theo bramstom",
"genderqueer", "english"] */
If any of the values of the current object matches the given string (term), add the current object to the hits array.
if (Object.values(now)
.map(val => val.toLowerCase()).includes(term.toLowerCase())) {
hits.push(now);
}
An object literal is returned.
{
"matches": /* an array of all matched objects */,
"total": /* the .length of "matches" array */
};
/* To get the answer prompted in OP -- do the following */
const x = dataFilter(students, "Math");
console.log(x.total);
// NOTE: key "class" is now "subject" just for aesthetics
const students=[{id:"01GN3Z1RYJJQHN588AX3BWS6QB",name:"Theo Bramstom",gender:"Genderqueer",subject:"English"},{id:"01GN3Z1RYM527HAX56ZN14F0YB",name:"Juli Marsy",gender:"Female",subject:"History"},{id:"01GN3Z1RYPYP1FFFEY55T92VX2",name:"Linc Espley",gender:"Non-binary",subject:"Math"},{id:"01GN3Z1RYR325M0QETVVPE2N5J",name:"Barbabas Grisley",gender:"Male",subject:"Math"},{id:"01GN3Z1RYTXA49SBQYXR9DMC04",name:"Godfree Braybrook",gender:"Male",subject:"English"},{id:"01GN3Z1RYVE4N5D16C8QWB1XGF",name:"Jason De Vuyst",gender:"Male",subject:"History"},{id:"01GN3Z1RYXY9WXF1Y407HXFYH8",name:"Adler McCanny",gender:"Male",subject:"Math"},{id:"01GN3Z1RYY9XV444J0SP5Y0QC2",name:"Noellyn MacMorland",gender:"Genderqueer",subject:"Math"},{id:"01GN3Z1RZ0HPQNZ1VKX8ZHA9ZY",name:"Padget Geldeford",gender:"Male",subject:"Math"},
{id:"01GN3Z1RZ2DZE92NG42KSGDXN9",name:"Milissent Treby",gender:"Female",subject:"Art"}];
const dataFilter = (array, term) => {
let result = array.reduce((hits, now) => {
if (Object.values(now).map(val => val.toLowerCase()).includes(term.toLowerCase())) {
hits.push(now);
}
return hits;
}, []);
return {"matches": result, "total": result.length};
}
console.log(dataFilter(students, "Math"));
// Control case: term === "Math"
console.log(dataFilter(students, "PE"));
// No match case: term != "PE"
console.log(dataFilter(students, "female"));
// Case insensitive case: term === "Female"
I am trying to join the array of objects internal properties with the comma , like as below
const multiSpaceIdentityInformation = spaces?.reduce(
(acc, space) => {
acc.roomName = `${acc.roomName},${space.spaceIdentity.roomName}`;
acc.roomNumber = `${acc.roomNumber},${space.spaceIdentity.roomNumber}`;
acc.storyName = `${acc.storyName},${space.buildingStory?.name}`;
acc.spaceNumber = `${acc.spaceNumber},${space.spaceIdentity.number}`;
acc.spaceName = `${acc.spaceName},${space.spaceIdentity.name}`;
return acc;
},
{
roomName: 'N/A',
roomNumber: 'N/A',
storyName: 'N/A',
spaceNumber:'N/A',
spaceName: 'N/A'
}
);
But somehow, I cannot display the information even I have spaces holding the array of objects.
What I am trying to display is if there is no information, I would like to say 'N/A' as the default option.
I am accessing the above information here
const identityData = [
{ label: 'Room Number', value: multiSpaceIdentityInformation.roomNumber },
{ label: 'Room Name', value: multiSpaceIdentityInformation.roomName },
{ label: 'Level', value: multiSpaceIdentityInformation.storyName },
{ label: 'Space Number', value: multiSpaceIdentityInformation.spaceNumber },
{ label: 'Space Name', value: multiSpaceIdentityInformation.spaceName }
];
Could anyone please let me know where it goes wrong with the above code?
Many thanks in advance!
Sample input
{
"Spaces": [
{
"spaceGeometry":{
"roomName": ""
"roomNumber": "",
"number": "number1"
"name": "space1"
},
"buildingStory":{
"name": "story1"
}
},
{
"spaceGeometry":{
"roomName": ""
"roomNumber": "",
"number": "number2"
"name": "space2"
},
"buildingStory":{
"name": "story2"
}
},
]
}
and desired output be like
multiSpaceIdentityInformation.roomName = "N/A"
multiSpaceIdentityInformation.roomNumber = "N/A"
multiSpaceIdentityInformation.storyName = "story1, story2"
multiSpaceIdentityInformation.spaceNumber = "number1, number2"
multiSpaceIdentityInformation.spaceName = "space1, space2"
The second parameter of reduce() is the initial value, so "N/A" will be rendered as long as spaces is an array. Here's what I would do:
const appendData = (initialValue, newValue) => {
if(!newValue) return initialValue;
if(!initialValue || initialValue === '') return newValue;
return `${initialValue}, ${newValue}`;
}
const multiSpaceIdentityInformation = spaces?.reduce(
(acc, space) => ({
roomName: appendData(acc.roomName, space.spaceIdentity.roomName),
roomNumber: appendData(acc.roomNumber, space.spaceIdentity.roomNumber),
storyName: appendData(acc.storyName, space.buildingStory?.name),
spaceNumber: appendData(acc.spaceNumber, space.spaceIdentity.number),
spaceName: appendData(acc.spaceName, space.spaceIdentity.name)
}),
{
roomName: '',
roomNumber: '',
storyName: '',
spaceNumber:'',
spaceName: ''
}
);
Object.keys(multiSpaceIdentityInformation).forEach((key) => {
if(multiSpaceIdentityInformation[key] === '')
multiSpaceIdentityInformation[key] = 'N/A';
});
So I have an array of objects with many, keys, something like that:
[
{ id: 1,
phoneNumber: 12345,
name: "John",
underLicense: true
},
{ id: 2,
phoneNumber: 12345,
name: "Jane",
underLicense: false
}
]
The way i want it to look like is this:
[
{ listPhone: [
{ number: 12345,
underLicense: true
},
{ number: 12345
underLicense: false
}
]
}
]
so for that, first i do the map(), and then I push it into listPhones
here is my function
saveLicense() {
const listPhone = this.toSend.map(x => {
return {
number: x.phoneNumber,
underLicense: x.underLicense
};
});
const savedPhones = [];
savedPhones.push({listPhone: listPhone});
}
The question is, is there a way to to it in the map() metod, without having to use push in the second step
You could directly map to an expression for a property value.
saveLicense() {
const
savedPhones = [{ listPhone: this.toSend.map(({ phoneNumber: number, underLicense }) =>
({ number, underLicense })
) }];
}
Maybe:
saveLicense () {
const listPhone = this.toSend.map((x) => ({
number: x.phoneNumber,
underLicense: x.underLicense,
}));
const savedPhones = [{ listPhone }];
};
saveLicense() {
const listPhone = this.toSend.map(x => {
return { listPhone: {
number: x.phoneNumber,
underLicense: x.underLicense
}
};
});
return [listPhone]
}
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"));
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);