Reputation: 18200
Let's say I have this:
const data = [
{
table: [
[{
textValue: 'One'
},
{
textValue: 'Two',
rows: 3
},
{
textValue: 'Three',
rows: 3
},
{
textValue: 'Four'
}],
[{
textValue: 'RED',
rows: 2
},
{
textValue: 'GREEN'
},
{
textValue: 'BLUE',
rows: 1
}]
]
}
];
What I am going after is where it traverses through the object (Object.entries()
would work?) and see that rows
exists and inserts X
number of empty ''
strings, so you'd have something like:
const data = [
{
table: [
[{
textValue: 'One'
},
{
textValue: 'Two',
rows: 3
},
'',
'',
'',
{
textValue: 'Three',
rows: 3
},
'',
'',
'',
{
textValue: 'Four'
}],
[{
textValue: 'RED',
rows: 2
},
'',
'',
{
textValue: 'GREEN'
},
{
textValue: 'BLUE',
rows: 1
},
''
]
]
}
];
I thought about using a for in
but then I won't know the parent object to edit it when it comes time to push the element.
Upvotes: 1
Views: 63
Reputation: 2181
Here is a solution that uses object-scan and is a bit more flexible. Using vanilla javascript might be the better choice, but that depends on your requirements
// const objectScan = require('object-scan');
const data = [{ table: [[ { textValue: 'One' }, { textValue: 'Two', rows: 3 }, { textValue: 'Three', rows: 3 }, { textValue: 'Four' } ], [ { textValue: 'RED', rows: 2 }, { textValue: 'GREEN' }, { textValue: 'BLUE', rows: 1 } ]] }];
const modify = (obj) => objectScan(['[*].table[*][*].rows'], {
rtn: 'count',
filterFn: ({ gparent, gproperty, value }) => {
gparent.splice(gproperty + 1, 0, ...Array(value).fill(''));
}
})(obj);
console.log(modify(data)); // returns number of modifications
// => 4
console.log(data);
// => [ { table: [ [ { textValue: 'One' }, { textValue: 'Two', rows: 3 }, '', '', '', { textValue: 'Three', rows: 3 }, '', '', '', { textValue: 'Four' } ], [ { textValue: 'RED', rows: 2 }, '', '', { textValue: 'GREEN' }, { textValue: 'BLUE', rows: 1 }, '' ] ] } ]
.as-console-wrapper {max-height: 100% !important; top: 0}
<script src="https://bundle.run/[email protected]"></script>
Disclaimer: I'm the author of object-scan
Upvotes: 0
Reputation: 50684
You can use .map()
and .flatMap()
which will return an array of your inserted string characters based on the number of rows
for the given object, that will be flattened into the resulting array:
const data = [{ table: [ [{ textValue: 'One' }, { textValue: 'Two', rows: 3 }, { textValue: 'Three', rows: 3 }, { textValue: 'Four' } ], [{ textValue: 'RED', rows: 2 }, { textValue: 'GREEN' }, { textValue: 'BLUE', rows: 1 } ] ] }];
const result = data.map(obj => ({
...obj,
table: obj.table.map(arr =>
arr.flatMap((iobj) => [iobj, ...Array(iobj.rows || 0).fill('')])
)
}));
console.log(result);
.as-console-wrapper { max-height: 100% !important;} /* ignore */
Upvotes: 3
Reputation: 6419
Instead of extending data object I would copy its content to a new table with proper reducer method to ease the process, shall be easy as:
const transformedTable = data[0].table.map(e => e.reduce((acc, val) => ([...acc, val, ...(new Array(val.rows || 0)).fill('')]), []));
const data = [
{
table: [
[{
textValue: 'One'
},
{
textValue: 'Two',
rows: 3
},
{
textValue: 'Three',
rows: 3
},
{
textValue: 'Four'
}],
[{
textValue: 'RED',
rows: 2
},
{
textValue: 'GREEN'
},
{
textValue: 'BLUE',
rows: 1
}]
]
}
];
const transformedTable = data[0].table.map(e => e.reduce((acc, val) => ([...acc, val, ...(new Array(val.rows || 0)).fill('')]), []));
document.querySelector('#result').innerText = JSON.stringify(transformedTable);
<pre id="result"></pre>
Upvotes: 1