Assign array values to an item in object - Javascript/React - javascript

I have an object with few items and I want to update the values of one property from array.
Object :
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 array and assign it to the options instead of hard coding it.
In this object of id phone:
options: [{ label: 'abc', value: 'abc' },
{ label: 'xyz', value: 'xyz' },
{ label: 'mno', value: 'mno' }]
}
];
array is coming from
this.props.phoneList
label and values will be this.props.phoneList[i].name
how to loop over this and get the latest values from the array

This should keep the order of the array intact also:
const newStructure = structure.map(item => {
const isPhone = item.id === “phone”
return {
...item,
options: isPhone ? this.props.phoneList : (item.options || undefined)
}
}

Related

Transform Object attribute to array of object

I want to merge Array of ObjectA containing ObjectB attribute by ObjectA attribute.
For example :
let myArray = [
{ name: 'Jeu', series: { name: 'testA', value: '89' } },
{ name: 'Dim', series: { name: 'testB', value: '490' } },
{ name: 'Dim', series: { name: 'testC', value: '978' } }
]
And I would like to transform it to
[
{ name: 'Jeu', series: { name: 'testA', value: '89' } },
{ name: 'Dim', series: [{ name: 'testB', value: '490' },{ name: 'testC', value: '978' } ] }
]
Am I able to do that with a simple reduce/map loop ?
You can first use reduce (with some spread syntax) to build an object that maps unique names and objects in the format you want to have, grouping series by name. Then, you can simply get the values from this object.
const myArray = [
{ name: 'Jeu', series: { name: 'testA', value: '89' } },
{ name: 'Dim', series: { name: 'testB', value: '490' } },
{ name: 'Dim', series: { name: 'testC', value: '978' } }
];
const map = myArray.reduce(
(acc, curr) => ({
...acc,
[curr.name]: {
name: curr.name,
series: acc[curr.name]
? [...acc[curr.name].series, curr.series]
: [curr.series]
}
}),
{}
);
const output = Object.values(map);
console.log(output);

How to use ternary operator while pushing elements into the array

I am trying to add the objects into the array based on the condition.
My expectation is to add two objects when the condition met but I am getting only the last object getting added (its element is missing).
const country = ‘USA’
citizenArray.push([
{
label: ‘Alex’,
value: ’32’,
},
country === ‘USA’
? ({
label: ‘John’,
value: ’28’,
},
{
label: ‘Miller’,
value: ’40’,
})
: {
label: ‘Marsh’,
value: ’31’,
},
]);
The output I am getting:
[{
label: ‘Alex’,
value: ’32’,
},
{
label: ‘Miller’,
value: ’40’,
}]
Expected:
[{
label: ‘Alex’,
value: ’32’,
},
{
label: ‘John’,
value: ’28’,
},
{
label: ‘Miller’,
value: ’40’,
}]
Could somebody help me point out where I am doing wrong?
Thanks.
In Javascript when you placed comma-separated expressions within parathesis it will execute each(left to right) and will return the result of last.
In your case ({ label: 'John', value: '28',}, { label: 'Miller', value: '40',}) results just the last object { label: ‘Miller’, value: ’40’, } and adds to the array.
To make it work to use an array and then use spread syntax to add them.
const country = 'USA';
const citizenArray = [];
citizenArray.push([{
label: 'Alex',
value: '32',
},
...(country === 'USA' ? [{
label: 'John',
value: '28',
}, {
label: 'Miller',
value: '40',
}] : [{
label: 'Marsh',
value: '31',
}])
]);
console.log(citizenArray);
Just use different logic like so:
const country = "USA";
let citizenArray = [];
citizenArray.push([{ label: "Alex", value: "32" }, ...(country == "USA" ? [{ label: "John", value: "28" }, { label: "Miller", value: "40" }] : [{ label: "Marsh", value: "31" }])]);
console.log(citizenArray);
.as-console-wrapper { max-height: 100% !important; top: auto; }
How about using the Spread ... operator
const myArray = [
...(condition1 ? [item1] : []),
...(condition2 ? [item2] : []),
...(condition3 ? [item3] : []),
];

Restructuring a JSON file in javascript

I have a JSON called 'from' that I want to convert to 'to' as follows. What is the fastest and most efficient way to achieve it? Is it possible to do in one step or should I reduce the duplicates first?:
const from =[{
NUM: '1234001',
SUBNUM: '001'},
{
NUM: '1234001',
SUBNUM: '001'},
{
NUM: '1234002',
SUBNUM: '002'},
{
NUM: '1234005',
SUBNUM: '005'},
{
NUM: '4567001',
SUBNUM: '001'},
{
NUM: '9999001',
SUBNUM: '001'}
];
const to = [{
label: 'SUBNUM',
submenu: [{
label: '1234',
role: '1234',
submenu: [{
label: '001',
role: '001'
},
{
label: '002',
role: '002'
},
{
label: '005',
role: '005'
}]
},{
label: '4567',
role: '4567',
submenu: [{
label: '001',
role: '001'
}]
},{
label: '9999',
role: '9999',
submenu: [{
label: '001',
role: '001'
}]
}
]}];
You can try following code:
let items = [];
from.forEach(obj => {
let numTruncated = obj.NUM.replace(obj.SUBNUM, "");
let currentNum = items.find(n => n.label === numTruncated);
if(!currentNum ) {
currentNum = {
label: numTruncated,
role: numTruncated,
submenu: []
};
items.push(currentNum );
}
if(!currentNum .submenu.find(item => item.label === obj.SUBNUM)){
currentNum .submenu.push({ label: obj.SUBNUM, role: obj.SUBNUM });
}
});
let output = { label: "SUBNUM", submenu: items };
find returns undefined if there's no element matching specified arrow function, using replace from string prototype to get rid of SUBNUM

How to find the first property that is an array in an object?

I'm creating a function that loops through an array like this:
schema: [{
name: 'firstRow',
fields: [{
name: 'name',
text: 'Name',
type: 'text',
col: 12,
value: ''
}]
}, {
And returns a callback with the values of the objects:
eachDeep (array, callback) {
array.forEach(item => {
item.fields.forEach(field => {
callback(field)
})
})
},
As you can see the item.fields.forEach part is harcoded. How can I modify the function so it detects the first property that it's an array and loop through it? (e.g. in this case that property is fields).
To find whether a property of an object is an array or not you can also use this one:
//let item be your object's property
if(typeof item == "object" && item.length > 0){
//do whatever if it is an array
}
You can check if the field is not an array or not, if so loop it, otherwise do something else with it.
var data = [{
name: 'firstRow',
fields: [{
name: 'name',
text: 'Name',
type: 'text',
col: 12,
value: ''
}]
}, {
name: 'firstRow',
fields: [{
name: 'name',
text: 'Name',
type: 'text',
col: 12,
value: ''
}]
}];
eachDeep (array, callback) {
array.forEach(item => {
// loop through each property again
item.forEach(prop => {
// if property is an array
if (prop instanceof Array) {
prop.forEach(field => callback(field));
} else {
// property is not an array
// do something else
}
})
})
},
var big_array =
[
{
name: 'firstRow',
fields: [{
name: 'name',
text: 'Name',
type: 'text',
col: 12,
value: ''
}]
}
];
for (let item of big_array)
{
for (let key in item)
{
if (Array.isArray(item[key]) )
{
console.log('this is an array do something:', key);
}
}
}
You could check using Array.isArray()
If the goal is to find the first array property you can do the following. Using ES6.
const schema = [{
name: 'firstRow',
fields: [{
name: 'name',
text: 'Name',
type: 'text',
col: 12,
value: ''
}]
}]
let firstArr;
schema.forEach(item => {
firstArr = Object.keys(item).filter(k => Array.isArray(item[k]))[0];
})

Concat array from Object from Array

I'm currently trying to retrieve a list of metadata stored as an array, inside an object, inside an array. Here's a better explanatory example:
[
{
name: 'test',
metadata: [
{
name: 'Author',
value: 'foo'
},
{
name: 'Creator',
value: 'foo'
}
]
},
{
name: 'otherTest',
metadata: [
{
name: 'Created',
value: 'foo'
},
{
name: 'Date',
value: 'foo'
}
]
},
{
name: 'finalTest'
}
]
Now, my objective is to retrieve a list of metadata (by their name) without redundancy. I think that .map() is the key to success but I can't find how to do it in a short way, actually my code is composed 2 for and 3 if, and I feel dirty to do that.
The expected input is: ['Author', 'Creator', 'Created', 'Date']
I'm developping in Typescript, if that can help for some function.
You can use reduce() and then map() to return array of names.
var data = [{"name":"test","metadata":[{"name":"Author","value":"foo"},{"name":"Creator","value":"foo"}]},{"name":"otherTest","metadata":[{"name":"Created","value":"foo"},{"name":"Date","value":"foo"}]},{"name":"finalTest"}]
var result = [...new Set(data.reduce(function(r, o) {
if (o.metadata) r = r.concat(o.metadata.map(e => e.name))
return r
}, []))];
console.log(result)
You could use Set for unique names.
var data = [{ name: 'test', metadata: [{ name: 'Author', value: 'foo' }, { name: 'Creator', value: 'foo' }] }, { name: 'otherTest', metadata: [{ name: 'Created', value: 'foo' }, { name: 'Date', value: 'foo' }] }, { name: 'finalTest' }],
names = new Set;
data.forEach(a => (a.metadata || []).forEach(m => names.add(m.name)));
console.log([...names]);
.as-console-wrapper { max-height: 100% !important; top: 0; }
var data = [{"name":"test","metadata":[{"name":"Author","value":"foo"},{"name":"Creator","value":"foo"}]},{"name":"otherTest","metadata":[{"name":"Created","value":"foo"},{"name":"Date","value":"foo"}]},{"name":"finalTest"}]
data
.filter(function(obj){return obj.metadata != undefined})
.map(function(obj){return obj.metadata})
.reduce(function(a,b){return a.concat(b)},[])
.map(function(obj){return obj.name})
A hand to hand Array.prototype.reduce() and Array.prototype.map() should do it as follows;
var arr = [
{
name: 'test',
metadata: [
{
name: 'Author',
value: 'foo'
},
{
name: 'Creator',
value: 'foo'
}
]
},
{
name: 'otherTest',
metadata: [
{
name: 'Created',
value: 'foo'
},
{
name: 'Date',
value: 'foo'
}
]
},
{
name: 'finalTest'
}
];
result = arr.reduce((p,c) => c.metadata ? p.concat(c.metadata.map(e => e.name))
: p, []);
console.log(result);

Categories

Resources