Is there a neater way to transform an array of objects - javascript

I am trying to transform an array, with only one of the values changed. Is there a neater way to do it?
I have attached the code that I have tried. It works, however I am only changing the number of the contact object for each user so it feels a little redundant to go through every other value to create a new formatted array. How can I replace just the contact number without going through everything?
const users = [
{
id: "1",
name: {
givenNames: 'SpongeBob',
last: 'SquarePants',
},
contact: {
email: '',
phone: '+1 123-1231234'
},
},
{
id: "2",
name: {
givenNames: 'Patrick',
last: 'Star',
},
contact: {
email: 'test2#test.com',
phone: '+1 123-123-1234',
},
},
{
id: "3",
name: {
givenNames: 'Eugene Harold',
last: 'Krabs',
},
contact: {
email: 'test3#test.com',
phone: '',
},
},
];
My code:
guestList() {
const formattedArray = this.getSelectedGuests.map(user => {
var rObj = {};
rObj.id = user.id;
rObj.name = user.name;
rObj.contact = {
email: user.contact.email,
phone: user.contact.phone.replace(/[&\/\\#,+()$~%.'":*?<>{}]/g, ''),
};
return rObj;
});
return formattedArray;
}
Output:
const users = [
{
id: "1",
name: {
givenNames: 'SpongeBob',
last: 'SquarePants',
},
contact: {
email: '',
phone: '11231231234'
},
},
{
id: "2",
name: {
givenNames: 'Patrick',
last: 'Star',
},
contact: {
email: 'test2#test.com',
phone: '11231231234',
},
},
{
id: "3",
name: {
givenNames: 'Eugene Harold',
last: 'Krabs',
},
contact: {
email: 'test3#test.com',
phone: '',
},
},
];

Since you only need to change a property inside contact, you can use object destructuring with rest, to extract contact from the rest of the object.
Now you can spread the rest of the object into the new one, create a new contact property, spread the contents of the original content into it, and override the phone property.
function guestList(getSelectedGuests) {
return getSelectedGuests.map(({ contact, ...rest }) => ({
...rest,
contacts: {
...contact,
phone: contact.phone.replace(/[&\/\\#,+()$~%.'":*?<>{}]/g, ''),
}
}));
}
const users = [{"id":"1","name":{"givenNames":"SpongeBob","last":"SquarePants"},"contact":{"email":"","phone":"+1 123-1231234"}},{"id":"2","name":{"givenNames":"Patrick","last":"Star"},"contact":{"email":"test2#test.com","phone":"+1 123-123-1234"}},{"id":"3","name":{"givenNames":"Eugene Harold","last":"Krabs"},"contact":{"email":"test3#test.com","phone":""}}];
const result = guestList(users);
console.log(result);
If you need to do a lot of immutable transformations, you might want to consider Immer. Immer allows you to use simple mutating code, and it ensures immutability using Proxies.
const { produce } = immer;
function guestList(getSelectedGuests) {
return getSelectedGuests.map(user => produce(user, draft => {
draft.contact.phone = user.contact.phone.replace(/[&\/\\#,+()$~%.'":*?<>{}]/g, '')
}));
}
const users = [{"id":"1","name":{"givenNames":"SpongeBob","last":"SquarePants"},"contact":{"email":"","phone":"+1 123-1231234"}},{"id":"2","name":{"givenNames":"Patrick","last":"Star"},"contact":{"email":"test2#test.com","phone":"+1 123-123-1234"}},{"id":"3","name":{"givenNames":"Eugene Harold","last":"Krabs"},"contact":{"email":"test3#test.com","phone":""}}];
const result = guestList(users);
console.log(result);
console.log(result[0] === users[0]); // false - a new object was created
<script src="https://unpkg.com/immer/dist/immer.umd.js"></script>

Well, as long as you don't use a library exposing Immutable objects implementation, this is the kind of code you have to write. Depending upon the JS dialect you have access to, you can write slightly shorter code, but the buld is still there:
guestList() {
return this.getSelectedGuests.map(user => ({
user.id,
user.name,
contact: {
user.contact.email,
phone: user.contact.phone.replace(/[&\/\\#,+()$~%.'":*?<>{}]/g, ''),
}
}));
}
If you want to work with immutability, I would strongly advise to have a look at something like Immutable.js (probably the one with the most diffusion) or Seamless Immutable (which has far less diffusion, but I like it a lot).

You can't avoid visiting each user because you have to change each user's contact property.
I am only changing the number of the contact object for each user so
it feels a little redundant to go through every other value to create
a new formatted array.
You can use spread syntax to copy object properties without explicitly copying them.
I also added hyphen - and whitespace character \s to the regex to get the desired output.
const users = [{ id: "1", name: { givenNames: 'SpongeBob', last: 'SquarePants', }, contact: { email: '', phone: '+1 123-1231234' }, }, { id: "2", name: { givenNames: 'Patrick', last: 'Star', }, contact: { email: 'test2#test.com', phone: '+1 123-123-1234', }, }, { id: "3", name: { givenNames: 'Eugene Harold', last: 'Krabs', }, contact: { email: 'test3#test.com', phone: '', }, } ];
let result = users.map(user => ({
...user,
contact: {
...user.contact,
"phone": user.contact.phone.replace(/[&\/\\#,+()$~%.'":*?<>{}-\s]/g, '')
}
}));
console.log(result);
In most cases, you shouldn't be concerned about creating new arrays because JavaScript and platforms it runs on optimize for such scenarios.
But if you want to modify the array in-place, you can use forEach() to do that.
const users = [{ id: "1", name: { givenNames: 'SpongeBob', last: 'SquarePants', }, contact: { email: '', phone: '+1 123-1231234' }, }, { id: "2", name: { givenNames: 'Patrick', last: 'Star', }, contact: { email: 'test2#test.com', phone: '+1 123-123-1234', }, }, { id: "3", name: { givenNames: 'Eugene Harold', last: 'Krabs', }, contact: { email: 'test3#test.com', phone: '', }, } ];
users.forEach(user => {
user.contact.phone = user.contact.phone.replace(/[&\/\\#,+()$~%.'":*?<>{}-\s]/g, '');
});
console.log(users);

Related

How to return multiple values from different arrays

lets say that you make a call to an API and get back an array of values like this
{
orders: [
{
id: '159151',
owner: 'steve',
created_at: '1662518452935217224',
}
]
}
to pull the id value I would normally write
const id = orders.orders[0].id
. sometimes however I get multiple back at the same time. it ranges from 1 - unknown and need to pull and input all the ids .
{
orders: [
{
id: '159151',
owner: 'steve',
created_at: '1662518452935217224',
},
{
id: '159152',
owner: 'john',
created_at: '1662518628829631781',
},
{
id: '159164',
owner: 'bob',
created_at: '1662519501403450193',
}
]
}
what can you do if you need to pull multiple id values at the same time but your unsure of the amount of id values that will be returned when you make the call to the API?
Assuming all the id keys in your example were the same (rather than idx). How about mapping them to an array?
const response = {
orders: [
{
id: '159151',
owner: 'steve',
created_at: '1662518452935217224',
},
{
id: '159152',
owner: 'john',
created_at: '1662518628829631781',
},
{
id: '159164',
owner: 'bob',
created_at: '1662519501403450193',
}
]
}
const ids = response.orders.map(order => order.id);
const count = ids.length
console.log(ids, count)
Use Array.prototype.map:
const data = { orders: [{ id: 12345 }, { id: 56789 }, { id: 192837 }] }
const ids = data.orders.map(o => o.id)
console.log(ids)
You can simply achieve that with a single line of code with the help of Array.map() method.
Live Demo :
const obj = {
orders: [
{
id: '159151',
owner: 'steve',
created_at: '1662518452935217224',
},
{
id: '159152',
owner: 'john',
created_at: '1662518628829631781',
},
{
id: '159164',
owner: 'bob',
created_at: '1662519501403450193',
}
]
};
const idsArr = obj.orders.map(({ id }) => id);
console.log(idsArr);

Why does this object contain `true` instead of the user name when logged?

I got an array with user info and user comments and I want to find which user left a specific comment. But when my function runs the console.log prints out this object:
{id: '7f053852-7440-4e44-838c-ddac24611050', firstName: false, lastName: 'Burke'}
and I’ve tried another comment but the results are not much different:
{id: 'b4a306cb-8b95-4f85-b9f8-434dbe010985', firstName: true, lastName: 'Marshall'}
Here my code:
var users = [
{
id: "88f24bea-3825-4237-a0d1-efb6b92d37a4",
firstName: "Sam",
lastName: "Hughes",
},
{
id: "2a35032d-e02b-4508-b3b5-6393aff75a53",
firstName: "Terri",
lastName: "Bishop",
},
{
id: "7f053852-7440-4e44-838c-ddac24611050",
firstName: "Jar",
lastName: "Burke",
},
{
id: "b4a306cb-8b95-4f85-b9f8-434dbe010985",
firstName: "Some string",
lastName: "Marshall"
}
];
const comments = [
{
userId: "88f24bea-3825-4237-a0d1-efb6b92d37a4",
text: "Great Job!"
},
{
userId: "7f053852-7440-4e44-838c-ddac24611050",
text: "Well done, I think I understand now!",
},
{
userId: "e789565f-fa5a-4d5e-8f6c-dd126cf995be",
text: "How do you do that? 😲",
},
{
userId: "7f053852-7440-4e44-838c-ddac24611050",
text: "OK great thanks"
},
{
userId: "b4a306cb-8b95-4f85-b9f8-434dbe010985",
text: "Cool, thanks!"
},
{
userId: "9e525c2d-6fcd-4d88-9ac4-a44eaf3a43e6",
text: "Nice one 😉"
}
];
var getuserbycom = users.find((user) => user.id === comments.find((comment) => comment.text === "Cool, thanks!").userId);
console.log(getuserbycom);
function findComment(comment) {
return comments.find(userComment => userComment.text === comment)
}
You will get the user Object. After that you can use the useId as required

How to map two array JSON to data in vue

I have JSON data that have two different arrays in one sheet.
I want to show each Organization Page then each page have every comment from the user who selects comment this organization.
{
ListOrg: {
id: 1613,
name_org: "US company",
rating: 0,
},
Review: [
{
review_id: 3,
org_id: 1613,
user_id: 2,
description: "Very good",
rating: 3,
user: {
id: 2,
name: "Kunjanaphorn",
firstname: "Kunjanaphorn",
lastname: "Boonmak",
admin: 0,
email: "Pim#gmail.com",
}
},
{
review_id: 4,
org_id: 1613,
user_id: 3,
description: "Not bad",
rating: 5,
user: {
id: 3,
name: "Kan",
firstname: "Kan",
lastname: "Tippayamontree",
admin: 0,
email: "First#gmail.com",
}
}
]
}
But I cannot map it to data in vue.js. I try this solution then it not work.
data() {
return {
Listorgs: [],
Reviews: [],
Listorg: {
name_org: "",
picture: "",
headerpic: "",
description: ""
}
mounted() {
axios.get("/api/listorgs/" + this.id).then(response => {
var listorg = response.data;
this.Reviews = listorg.Review;
this.Listorgs = listorg.Listorg;
});
}
Can you tell me about syntax
I want some attribute in each array -> name_org(string) from array ListOrg, description(string) from array Review, name(string) and firstname(string) from user array in Review array for show in vue page
I have helped you changed a little bit and made it work, check it out.
https://jsfiddle.net/fLvy3am9/
var listorg = response.data;
this.orgData = listorg.ListOrg;
this.reviews = listorg.Review.map((review) => {
return {
name_org: listorg.ListOrg.name_org,
description: review.description,
user: review.user
};
});
Ask me if there's any question.

How to loop through properties of objects inside of an array within a React component?

Here is my Parent component's render function:
render() {
const users = [
'tom': {
phone: '123',
email: 'hotmail'
},
'rob': {
phone: '321',
email: 'yahoo'
},
'bob': {
phone: '333',
email: 'gmail'
},
];
const list = users.map((user) =>
(<User
name={user}
phone={users.phone}
email={users.email}
/>),
);
return <ul>{list}</ul>;
}
The output shows up like this:
And here is the Child component's render function:
render() {
const {
name,
phone,
email,
} = this.props;
const info = [name, phone, email];
const item = info.map((index) => (
<li key={index}>
{ index }
</li>
));
return item;
}
How can I get it to show with the phone numbers and emails? Not sure what I'm doing incorrectly. Thanks.
At first this is not valid javascript:
const users = [
'tom': {
phone: '123',
email: 'hotmail'
},
// ...
];
You should either define an array or an object. Let's say your users is an object literal:
const users = {
'tom': {
phone: '123',
email: 'hotmail'
},
// ...
};
Then you can iterate over entries of the object:
const list = Object.entries(users).map(([name, info]) =>
(<User
name={name}
phone={info.phone}
email={info.email}
/>)
);
However Object.entries() is not supported in all browsers, check if it works in your environment.
First thing is that users is not a valid array If you want key value pair in main scope then use Object({})
render() {
const users = {
'tom': {
phone: '123',
email: 'hotmail'
},
'rob': {
phone: '321',
email: 'yahoo'
},
'bob': {
phone: '333',
email: 'gmail'
},
};
const list = Object.keys(users).map((user) =>
(<User
name={user}
phone={users[user].phone}
email={users[user].email}
/>),
);
return <ul>{list}</ul>;
}
You need to be referring to "user" instead of "users" inside of the Parent component's map function. The purpose of the "user" variable is to represent the current instance of each element in the array. So the map function should look like:
const list = users.map((user) =>
(<User
name={user}
phone={user.phone}
email={user.email}
/>),
);
instead.
One solution is to change your "list" to an actual list:
const users = [
{
name: 'tom',
phone: '123',
email: 'hotmail'
},
{
name: 'rob,
phone: '321',
email: 'yahoo'
},
{
name: 'bob',
phone: '333',
email: 'gmail'
},
];
Now user user.name instead of user.
Alternatively, create an object keyed by the names of each user:
const users = {
'tom': {
phone: '123',
email: 'hotmail'
},
'rob': {
phone: '321',
email: 'yahoo'
},
'bob': {
phone: '333',
email: 'gmail'
},
};
Then map over the keys:
const list = Object.keys(users).map((user) =>
(<User
name={user}
phone={users[user].phone}
email={users[user].email}
/>),
);
Your const users should be modified to map through them.
const users = [
{
name: 'tom',
phone: '123',
email: 'hotmail',
},
{
name:'rob',
phone: '321',
email: 'yahoo'
},
{
name: 'bob',
phone: '333',
email: 'gmail'
},
];
const list = users.map((usr =>
(<User
name={usr.name}
phone={usr.phone}
email={usr.email}
/>),
);
return <ul>{list}</ul>;
}

sort array of objects based on string

Suppose we have an array like
var a = [
{ name: 'Tom', surname: 'TestAsIvanov' },
{ name: 'Kate', surname: 'Ivanova' },
{ name: 'John', surname: 'Alivanov' },
{ name: 'Ivan', surname: 'Ivanov' }
]
I need to sort this array by surname field based on a provided string, e.g.:
for 'iva' the pattern array should be sorted as follows
var newA = [
{ name: 'Ivan', surname: 'Ivanov' },
{ name: 'Kate', surname: 'Ivanova' },
{ name: 'John', surname: 'Alivanov' },
{ name: 'Tom', surname: 'TestAsIvanov' },
]
for 'a' the pattern array should be sorted as follows
var newA = [
{ name: 'John', surname: 'Alivanov' },
{ name: 'Ivan', surname: 'Ivanov' },
{ name: 'Kate', surname: 'Ivanova' },
{ name: 'Tom', surname: 'TestAsIvanov' },
]
So arrays should be ordered by string pattern provided. How is it possible to implement this?
I've made a simple sort script for that. I don't know if it is the best way because I had to use two sort() methods, one to sort alphabetically(taken from here) and another to simulate a LIKE 'string%'(comparing to SQL) to get your condition:
var queryString = "iva";
a = a.sort(function(a, b) {
var s1 = a.surname.toUpperCase().indexOf(queryString.toUpperCase());
var s2 = b.surname.toUpperCase().indexOf(queryString.toUpperCase());
return (s1 > -1 && s1 > s2);
});
Fiddle with full code
At least it worked with both examples you provided, but I'm not sure if it is all you need.

Categories

Resources