This question already has answers here:
How can I group an array of objects by key?
(32 answers)
Closed 3 years ago.
I want to modify the data that API provides to client. I can only retrieve the unique category value using Set. Then I'm stuck how to proceed further.
const serverData = [
{
category: 'address',
label: 'Street',
type: 'text'
},
{
category: 'address',
label: 'Country',
type: 'text'
},
{
category: 'person',
label: 'FirstName',
type: 'text'
},
{
category: 'person',
label: 'LastName',
type: 'text'
}
];
I want the above to be modified like below. There can be many categories
const modifiedData = {
address : [
{
label: 'Street',
type: 'text'
},
{
label: 'Country',
type: 'text'
},
],
person : [
{
label: 'FirstName',
type: 'text'
},
{
label: 'LastName',
type: 'text'
}
]
};
Please help me achieve this. Thanks in advance!
You could use the reduce function to format your data. Here is an example:
const serverData = [
{
category: 'address',
label: 'Street',
type: 'text'
}, {
category: 'address',
label: 'Country',
type: 'text'
}, {
category: 'person',
label: 'FirstName',
type: 'text'
}, {
category: 'person',
label: 'LastName',
type: 'text'
}
];
const formatData = data => {
return data.reduce((result, item) => ({
...result,
[item.category] : [
...(result[item.category] || []),
item
]
}), {});
}
console.log(formatData(serverData));
Related
I am trying to loop through a nested object that looks like this:
let obj = {
cols: [
{ name: 'name', type: 'String' },
{ name: 'dob', type: 'Number' },
{ name: 'address', type: 'String' },
{ name: 'income', type: 'String' },
{ name: 'vehicleNumber', type: 'Number' },
{ name: 'assets', type: 'Number' }
],
row: [
{
name: 'randomInfo',
columns: ['name', 'address', 'assets'],
}
]
}
I am using the logic below to loop through the object's arrays, compare if they are equal, and if they are, I am returning them in an array. I am trying to return the entire object inside the cols key though. For e.g, if there are matching elements inside cols array' name value with the row array's columns key's value, (cols.name === row.columns[element], if there is a match return cols object)
//loop through the obj and get the keys before this
let cols = cols.map(col => col.name);
let row = row.map(ind => ind.columns);
let rowNamesFlattened = [].concat.apply([], row);
let matchingCols = cols.filter(element => row.includes(element));
The matchingCols object now has the matching names, but I want to ultimately return their type as well. Any idea how this can be done?
you can use filter directly on the cols array. However here I assumed that row array has only 1 element
let obj = {
cols: [
{ name: 'name', type: 'String' },
{ name: 'dob', type: 'Number' },
{ name: 'address', type: 'String' },
{ name: 'income', type: 'String' },
{ name: 'vehicleNumber', type: 'Number' },
{ name: 'assets', type: 'Number' }
],
row: [
{
name: 'randomInfo',
columns: ['name', 'address', 'assets'],
}
]
}
let matchingCols = obj.cols.filter(({name}) => obj.row[0].columns.includes(name))
console.log(matchingCols)
In case multiple elements present inside row array. can use flatMap to get flattened list of columns and then the same procedure as above
let obj = {
cols: [
{ name: 'name', type: 'String' },
{ name: 'dob', type: 'Number' },
{ name: 'address', type: 'String' },
{ name: 'income', type: 'String' },
{ name: 'vehicleNumber', type: 'Number' },
{ name: 'assets', type: 'Number' }
],
row: [
{
name: 'randomInfo',
columns: ['name', 'address', 'assets'],
},
{
name: 'randomInfo2',
columns: ['dob','name'],
}
]
}
let filtered = obj.cols.filter(({name}) => obj.row.flatMap(ind => ind.columns).includes(name))
console.log(filtered)
Another solution to get both matched and unmatched in one go using reduce. so no need 2 filter calls. referenced this
let obj = {
cols: [
{ name: 'name', type: 'String' },
{ name: 'dob', type: 'Number' },
{ name: 'address', type: 'String' },
{ name: 'income', type: 'String' },
{ name: 'vehicleNumber', type: 'Number' },
{ name: 'assets', type: 'Number' }
],
row: [
{
name: 'randomInfo',
columns: ['name', 'address', 'assets'],
},
{
name: 'randomInfo2',
columns: ['dob','name'],
}
]
}
let flatted = obj.row.flatMap(ind => ind.columns);
const result = obj.cols.reduce((acc, curr) => {
acc[flatted.includes(curr.name) ? 'match' : 'unmatch'].push(curr);
return acc;
}, { match: [], unmatch: [] });
console.log(result)
In a project that I'm working on, we're using the Angular library called formly to create our forms dynamically.
Currently, the form configuration is hardcoded as a Typescript object called mockForm. All of the properties in mockForm are hardcoded besides the options property in objects whose type property equals 'select':
mockForm
export const mockForm = {
name: 'root',
subSections: [
{
name: 'Client',
subSections: [
{
name: 'Contact Information'
},
{
name: 'Insurance Information'
}
]
},
{
name: 'Sales',
subSections: [
{
name: 'Overview',
subSections: [
{
name: 'Overview - A',
fields: [
{
key: 'fieldA1',
type: 'input',
templateOptions: {
label: 'A1',
required: true
}
},
{
key: 'fieldA2',
type: 'select',
templateOptions: {
label: 'A2',
required: true,
options: []
}
}
]
},
{
name: 'Overview - B',
fields: [
{
key: 'fieldB1',
type: 'input',
templateOptions: {
label: 'B1',
required: false
}
},
{
key: 'fieldB2',
type: 'select',
templateOptions: {
label: 'B2',
required: false,
options: []
}
}
]
}
]
}
]
}
]
};
I would like to populate the options property by using an API called which returns the following object:
API return
{
"multi_value_fields": {
"fieldA2": [
"froodian#outlook.com",
"gastown#sbcglobal.net",
"dgriffith#me.com",
"maradine#live.com",
"samavati#icloud.com",
"naupa#comcast.net"
],
"fieldB2": [
"<3m",
"<6m",
"<9m",
"<12m",
"+12m",
"N/A"
]
}
}
The object returned from the API call returns a JSON whose properties are the key values from mockForm whose property type equals 'select'; and the values of these JSON properties represent the dropdown options of the form.
The intended outcome should be the following:
export const mockForm = {
name: 'root',
subSections: [
{
name: 'Client',
subSections: [
{
name: 'Contact Information'
},
{
name: 'Insurance Information'
}
]
},
{
name: 'Sales',
subSections: [
{
name: 'Overview',
subSections: [
{
name: 'Overview - A',
fields: [
{
key: 'fieldA1',
type: 'input',
templateOptions: {
label: 'A1',
required: true
}
},
{
key: 'fieldA2',
type: 'select',
templateOptions: {
label: 'A2',
required: true,
options: [
"froodian#outlook.com",
"gastown#sbcglobal.net",
"dgriffith#me.com",
"maradine#live.com",
"samavati#icloud.com",
"naupa#comcast.net"
]
}
}
]
},
{
name: 'Overview - B',
fields: [
{
key: 'fieldB1',
type: 'input',
templateOptions: {
label: 'B1',
required: false
}
},
{
key: 'fieldB2',
type: 'select',
templateOptions: {
label: 'B2',
required: false,
options: [
"<3m",
"<6m",
"<9m",
"<12m",
"+12m",
"N/A"
]
}
}
]
}
]
}
]
}
]
};
I haven't experienced a scenario like this, and I'm not so sure on how to approach this (Should I start with the JSON properties and map back to mockForm? Would I need to manually iterate through mockForm in order to populate from the API call?)
your JSON mockForm is very typical.
If it remains the same then you must manually iterate over the bottom leaf i.e., mokeForm.subSections[1].subSections and then loop there to match the label & type.
Otherwise, you need to write parse which iterates all over mokeForm JSON & assign required options are respective places.
I have an object with few items and I want to update the values of one property options from another object.
Object 1 :
structure = [
{
id: 'name',
label: 'Name',
filterType: 'text',
filterOn: 'contains'
},
{
id: 'address',
label: 'Address',
filterType: 'text',
filterOn: 'contains'
},
{
id: 'phone',
label: 'Phone',
filterType: 'select',
filterOn: 'contains',
options: [{ label: 'abc', value: 'abc' },
{ label: 'xyz', value: 'xyz' },
{ label: 'mno', value: 'mno' }]
}
];
if the id is phone then I want to get the values from the object 2 phoneList and assign it to the options instead of hard coding it.
options: [{ label: 'abc', value: 'abc' },
{ label: 'xyz', value: 'xyz' },
{ label: 'mno', value: 'mno' }]
}
];
object 2 is
this.props.phoneList = [{name: 'aaa', age: 11},{name : 'bbb' , age : 12}, and so on
]
label and values will be this.props.phoneList[i].name
how to loop over this and get the latest values from the other object
First use filter to identify the object with id phone. Then use map to transform this.probs.phoneList in the desired format and assign to options.
structure.filter (x => x.id == 'phone')[0].options = this.probs.phoneList.map (x => ({label: x.name, value: x.name}));
Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 3 years ago.
Improve this question
Sorry if this is a bit confusing, but I have this array:
[
{
name: 'id',
type: 'string',
primary: true
},
{
name: 'notes',
type: 'text',
default: '[]'
},
{
name: 'reminders',
type: 'text',
default: '[]'
}
]
How would I turn it into
{
notes: '[]',
reminders: '[]'
}
? Here's the logic: Any index with a default property, set the key in the new object to the index's name, and set the value to the index's default.
You can make it with reduce
var array = [
{
name: 'id',
type: 'string',
primary: true
},
{
name: 'notes',
type: 'text',
default: '[]'
},
{
name: 'reminders',
type: 'text',
default: '[]'
}
]
var result = array.reduce((prev, el) => {
if (el.default) {
prev[el.name] = el.default
}
return prev;
},{})
console.log(result);
You can use filter with Object.keys().
// Your initial array
const initialArray = [{
name: 'id',
type: 'string',
primary: true
},
{
name: 'notes',
type: 'text',
default: '[]'
},
{
name: 'reminders',
type: 'text',
default: '[]'
}
];
// Array just with items that haves a default value
const itensWithDefaultValue = initialArray.filter(item => Object.keys(item).includes('default'));
// Object to save items
let objectWithValues = {};
// Save items in object with name and you default value
itensWithDefaultValue.map(item => objectWithValues[item.name] = item.default);
console.log(objectWithValues);
Hope this helps!
const data = [
{
name: 'id',
type: 'string',
primary: true
},
{
name: 'notes',
type: 'text',
default: '[]'
},
{
name: 'reminders',
type: 'text',
default: '[]'
}
];
const result = Object.fromEntries(
data
.filter(it => "default" in it)
.map(it => ([it.name, it.default]))
);
console.log(result);
Use reduce:
const arr = [{
name: 'id',
type: 'string',
primary: true
},
{
name: 'notes',
type: 'text',
default: '[]'
},
{
name: 'reminders',
type: 'text',
default: '[]'
}
];
const obj = arr.reduce((acc, curr) => curr.default ? { ...acc,
[curr.name]: curr.default
} : acc);
console.log(obj);
You could spread new objects into a single object.
var data = [{ name: 'id', type: 'string', primary: true }, { name: 'notes', type: 'text', default: '[]' }, { name: 'reminders', type: 'text', default: '[]' }],
result = Object.assign({}, ...data.map(({ name, default: d }) => d && { [name]: d }));
console.log(result);
I'm trying to display contacts in a table where it's possible to enter multiple contacts for the same address. I defined the settings for reactive table like this :
Template.masterlist.helpers({
settings: function() {
return {
collection: Prospects,
rowsPerPage: 10,
showFilter: true,
showColumnToggles: true,
fields: [
{
'key': 'address.streetNumber',
label: 'Street Number'
}, {
'key': 'address.streetName',
label: 'Street Name'
}, {
'key': 'address.streetApp',
label: 'App.'
}, {
'key': 'address.city',
label: 'City'
}, {
'key': 'address.province',
label: 'Province'
}, {
'key': 'address.postalCode',
label: 'Postal Code'
}, {
'key': 'contacts.0.name',
label: 'Name'
}, {
'key': 'contacts.0.phone',
label: 'Phone'
}, {
'key': 'contacts.0.email',
label: 'Email'
}, {
'key': 'contacts.0.notes',
label: 'Notes'
}
]
};
}
The problem is that it displays only the contact info for the first contact at this address I tried using [0] instead of just '0' but it didn't change anything.
Any idea?