Reputation: 1808
I cannot get my head around this problem.
I have a settings object which looks like
const setting = [
{
Key: 'root/',
Value: null,
},
{
Key: 'root/second-root/',
Value: null,
},
{
Key: 'root/second-root/names/',
Value: null,
},
{
Key: 'root/second-root/names/capital-letter',
Value: true,
},
{
Key: 'root/second-root/countries/',
Value: null,
},
{
Key: 'root/second-root/countries/enabledcountries',
Value: 'US,UK,DK',
},
{
Key: 'root/second-root/countries/async',
Value: 'true',
},
{
Key: 'root/second-root/countries/manual',
Value: 'true',
},
{
Key: 'root/second-root/countries/limit',
Value: '4200',
},
{
Key: 'root/second-root/names/onyl-last-name',
Value: false,
},
];
I need to convert it to look like
const wantedResult = [
{
'root': {
'Value': null,
'second-root': {
'Value': null,
'names': {
'Value': null,
'capital-letter': {
'Value': true,
}
'onyl-last-name': {
'Value': false,
}
},
'countries': {
'Value': null,
'enabledcountries': {
Value: 'US,UK,DK',
},
'async': {
Value: 'true',
},
'manual': {
Value: 'true',
},
'limit': {
Value: '4200',
}
}
}
}
}
];
The it is the Key property which controls the hierarchy. If it ends with a / the item is a directory else it is a value.
Problem is that the flat structure doesnt have to return the items in a correct order. Like in the example, the last item is 'root/second-root/names/onyl-last-name',
even though the names hiarchy was in the beginning of the flat structure.
I have tried a form of array.reduce but get stuck every time. Could someone please help me.
Upvotes: 2
Views: 833
Reputation: 386560
You could iterate the array and take the value without the last slash and split it as path to the object for assigning the value.
If necessary put the result in an array.
In forEach
works
a destructuring assignment for getting the key and value out of the object,
a replacement which looks for a slash at the end of the string with an empty string,
a splitting of the string by slash, it returns an array with strings without slashes,
using Array#reduce
with the result object as accumulator.
Inside it uses a default pattern with a logical OR ||
which check if the left side is a truthy value and if not, it assigns an object. This value is returned for the check with the next key.
at the end of the iteration it retuns an object reference and then the value gets assigned.
var setting = [{ Key: 'root/', Value: null }, { Key: 'root/second-root/', Value: null }, { Key: 'root/second-root/names/', Value: null }, { Key: 'root/second-root/names/capital-letter', Value: true }, { Key: 'root/second-root/countries/', Value: null }, { Key: 'root/second-root/countries/enabledcountries', Value: 'US,UK,DK' }, { Key: 'root/second-root/countries/async', Value: 'true' }, { Key: 'root/second-root/countries/manual', Value: 'true' }, { Key: 'root/second-root/countries/limit', Value: '4200' }, { Key: 'root/second-root/names/onyl-last-name', Value: false }],
result = {};
setting.forEach(({ Key, Value }) => Key
.replace(/\/$/, '')
.split('/')
.reduce((o, k) => o[k] = o[k] || {}, result).Value = Value
);
console.log(result);
.as-console-wrapper { max-height: 100% !important; top: 0; }
Upvotes: 3