I am trying to make a function that maps the data2 object value to the name of the data1.
I tried to iterate data2 object2 with data1 but it is not working properly. I am able to map them but not getting the value of data1 when it is not there in data2.
Is there any way I can map properly to get the desired output mentioned in the code?
let data1 = {
attributes: [{
Id: 'test1',
Name: 'Test1',
Type: 'date'
},
{
Id: 'test2',
Name: 'Test2',
Type: 'string'
},
{
Id: 'test3',
Name: 'Test3',
Type: 'string'
},
{
Id: 'test4',
Name: 'Test4',
Type: 'boolean'
}
]
};
let data2 = {
value: [{
test1: '10-12-2021',
test2: '4',
dummy: 'ignore me'
},
{
test3: '3',
test4: true,
abc: 'ignore me'
},
{
test1: '12-12-2023',
test3: '42',
dummy1: 'ignore me'
}
]
};
//output
let ouput = {
rows: [{
Test1: '10/12/2021',
Test2: '4',
Test3: '',
Test4: ''
},
{
Test1: '',
Test2: '',
Test3: '3',
Test4: 'Y'
},
{
Test1: '12/12/2023',
Test2: '',
Test3: '42',
Test4: ''
}
]
};
//function
function mapper(data1, data2) {
let formattedValue = [];
data2.value.forEach(val => {
let data = {};
for (let prop in val) {
let name;
const filter = data1.attributes.filter(el => el.Id === prop)[0];
if (filter) {
name = filter.Name;
switch (filter.Type) {
case 'boolean':
data[name] =
val[prop] === true ? 'Y' : val[prop] === false ? 'N' : '';
break;
case 'date':
data[name] = new Date(val[prop]).toLocaleDateString();
break;
default:
data[name] = val[prop];
break;
}
}
}
formattedValue.push(data);
});
return formattedValue;
}
console.log(mapper(data1, data2));
same if I pass data2 as empty value I am looking to get below output
let data1 = {
attributes: [
{
Id: 'test1',
Name: 'Test1',
Type: 'string'
},
{
Id: 'test2',
Name: 'Test2',
Type: 'string'
},
{
Id: 'test3',
Name: 'Test3',
Type: 'string'
},
{
Id: 'test4',
Name: 'Test4',
Type: 'boolean'
}
]
};
let data2 = {
value: [
]
};
//output
let ouput = {
rows: [
{
Test1: '',
Test2: '',
Test3: '',
Test4: ''
},
]
};
The keys in Map are ordered in a simple, straightforward way: A Map object iterates entries, keys, and values in the order of entry insertion. Although the keys of an ordinary Object are ordered now, this was not always the case, and the order is complex.
With a map method, you can order any number of objects by calling each object's map method once to map that object to a position on the axis used for the comparison, such as a number or date.
Iterate through a Map using JavaScript # Use the forEach() method to iterate over a Map object. The forEach method takes a function that gets invoked for each key/value pair in the Map , in insertion order. The function gets passed the value, key and the Map object on each iteration.
const data1 = {attributes:[{Id:'test1',Name:'Test1',Type:'date'},{Id:'test2',Name:'Test2',Type:'string'},{Id:'test3',Name:'Test3',Type:'string'},{Id:'test4',Name:'Test4',Type:'boolean'}]}
data2 = {value:[{test1:'10-12-2021',test2:'4'},{test3:'3',test4:true},{test1:'12-12-2023',test3:'42'}]};
data3 = {value: []}
const mapper = (x, y) => {
const row = x.attributes.map(e => [e.Id, e.Name])
format = e => { switch (true) {
case typeof e === 'boolean':
return e ? 'Y' : 'N'
case isNaN(e) && !isNaN(Date.parse(e)):
return new Date(e).toLocaleDateString()
default: return e
}}
const rows = (y.value.length ? y.value : [1]).map(e =>
Object.fromEntries(row.map(([k, v]) => [v, format(e[k]) ?? '']))
)
return { rows }
}
console.log(mapper(data1, data2))
console.log(mapper(data1, data3))
.as-console-wrapper { max-height: 100% !important; top: 0; }
Explanation:
y.value.length ? y.value : [1]
Checks if data.value
is empty, if not returns data.value
. If yes returns array
with 1 element (can be any value, it is just needed to do 1 iteration to meet your requirement about empty data, so value doesn't really matter here.
Rest of code should be pretty clear, if not, let me know.
UPDATE
because you want minimum one set of values even data2.values
is empty. My already given solution will work if we add empty object when array is empty, so adding below will fix it.
// I had to add below lines to get your desired result
// if `data2.value` is empty array
const arrayToLoop = [...data2.value];
if(arrayToLoop.length === 0) {
arrayToLoop.push({});
}
and now we will loop variable arrayToLoop
rather than data2.value
also wrote small function used to convert the value as per given type, you can extend it as per your own need
function parseValue(type, value){
if(value.length==0){
return '';
}
switch(type.toLowerCase()){
case 'boolean':
return value === true ? 'Y' : value === false ? 'N' : '';
case 'date':
return new Date(value).toLocaleDateString();
default:
return value;
}
}
first I will get all the key and label mapping, and will look all the values for each key. notice how I done below.
let me know if you face any prob.
function parseValue(type, value){
if(value.length==0){
return '';
}
switch(type.toLowerCase()){
case 'boolean':
return value === true ? 'Y' : value === false ? 'N' : '';
case 'date':
return new Date(value).toLocaleDateString();
default:
return value;
}
}
function BusinessObjectMapper(data1, data2){
const arrayToLoop = [...data2.value];
if(arrayToLoop.length === 0) {
arrayToLoop.push({});
}
const rows = arrayToLoop.map(v=>{
let r = {};
data1.attributes.forEach(o=>{
let {Id, Name, Type} = o;
r[Name]=parseValue(Type, v[Id]||'');
})
return r;
})
return {
rows
};
}
let data1 = {
attributes: [
{
Id: 'test1',
Name: 'Test1',
Type:'string'
},
{
Id: 'test2',
Name: 'Test2',
Type:'boolean',
},
{
Id: 'test3',
Name: 'Test3',
Type:'date'
},
{
Id: 'test4',
Name: 'Test4',
Type:'un-known',
}
]
};
let data2 = {
value: [
{
test1: '1',
test2: true
},
{
test3: '02/02/2020',
test4: '42'
},
{
test1: 'deepak',
test3: '01/01/2021'
}
]
};
let data2_empty = {
value: []
}
console.log(BusinessObjectMapper(data1, data2));
console.log(BusinessObjectMapper(data1, data2_empty));
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With