I'm using Angular, and I have input data in the following structure, key = string, value = array of strings:
inputObject= {
'employees': [
'bob/january',
'bob/january-february',
'bob/january-march',
'steve/january',
'steve/january-february',
'steve/january-march',
'september',
],
};
I need to transform this object by splitting the values using '/' as a delimiter, so splitting the string elements in the employees array and put that in a new object where the string value before the '/' becomes the key of the new object and the string values after the '/'are added as an array of string values. if the value in the employees element does not have a '/' in the string then the key should be a hardcoded string value such as 'n/a' as seen below
Desired Output:
outputObject = {
'bob': [
'january',
'january-february',
'january-march'
],
'steve': [
'january',
'january-february',
'january-march',
],
'n/a': 'september'
}
I have tried various techniques, one such example as seen in the snippet where I attempted to add to a map. This would work by adding to a new object or any other data structure that you could recommend.
inputObject= {
'employees': [
'bob/january',
'bob/january-february',
'bob/january-march',
'steve/january',
'steve/january-february',
'steve/january-march',
'september',
],
};
let outputMap = new Map();
let splitValues = inputObject.employees.map(a => a.split('/'));
console.log(splitValues)
splitValues.forEach(a => {
if(a.length > 1){
outputMap.set(a[0], a[1]);
} else {
outputMap.set('n/a', a[0])
}
});
console.log(outputMap)
<iframe name="sif1" sandbox="allow-forms allow-modals allow-scripts" frameborder="0"></iframe>
Stackblitz: https://stackblitz.com/edit/angular-ivy-ogbdwv
CodePudding user response:
You may use Array.prototype.reduce()
to group items and String.prototype.match()
to implement splitting logic:
const input = {
employees: [
'bob/january',
'bob/january-february',
'bob/january-march',
'steve/january',
'steve/january-february',
'steve/january-march',
'september',
]
},
output = input.employees
.reduce((acc, str) => {
const [key = 'n/a', value] = str
.match(/(([^/] )\/)?(. )/)
.slice(2)
const group = acc[key]
group
? group.push(value)
: acc[key] = [value]
return acc
}, {})
console.log(output)
.as-console-wrapper{min-height:100%;}
<iframe name="sif2" sandbox="allow-forms allow-modals allow-scripts" frameborder="0"></iframe>
CodePudding user response:
Reduce is perfect for changing one data structure to another.
It might look like this (untested):
type Output = {
[name:string]: string[]
}
const output = inputObject.employees.reduce<Output>((acc, curr) => {
const splitStr = curr.split('/')
if (splitStr.length === 1) {
return {
...acc,
'n/a': [
...acc['n/a'],
splitStr[0]
]
}
}
const [name, date] = splitStr;
return {
...acc,
[name]: acc[name]?.length > 0
? [...acc[name], date]
: [date]
}
}, {});
console.log(output);