What is the best way to convert plain text data like:
[group a]
a
b
c
[group b]
a
d
f
Into an object...
{
groupA: ['a', 'b', 'c'],
groupB: ['a', 'd', 'f']
}
The plain text data will vary in length, but the structure will always be represented like:
[parent group]
child item 1
child item 2
...
CodePudding user response:
You can use split and reduce
const string = `[group a]
a
b
c
[group b]
a
d
f`
const list = string.split(`\n`)
let saveKey;
const obj = list.reduce((acc,cur) => {
if (cur.startsWith('[')) {
const groupLetter = cur.match(/ (\w )\]/)[1].toUpperCase()
saveKey = `group${groupLetter}`;
acc[saveKey]=[];
}
else {
acc[saveKey].push(cur);
}
return acc
},{})
console.log(obj)
CodePudding user response:
You can grab all the lines of text and reduce the lines by parsing and determining if it is a key or a value. Your accumulator needs to store both the results and the current key.
const
parse = (text) =>
text.trim().split('\n')
.reduce((acc, line) => {
const match = line.trim().match(/^\[(. )\]$/);
return match
? { ...acc, key: match[1] }
: { ...acc, result: { ...acc.result,
[acc.key]: [...(acc.result[acc.key] ?? []), line.trim()] }
};
}, { result: {}, key: null }).result,
data = parse(document.querySelector('#data').value);
console.log(data);
.as-console-wrapper { top: 0; max-height: 100% !important; }
#data { display: none; }
<textarea id="data">[group a]
a
b
c
[group b]
a
d
f</textarea>
CodePudding user response:
Make an array of the original string by splitting on \n
, then loop through and create the object:
const str = `[group a]
a
b
c
[group b]
a
d
f`
const arr = str.split('\n')
const obj = {}
let curHeader
arr.forEach(el =>
{
if(el[0] === '[')
{
let frmtEl = el.substring(1, el.length-1)
let frmtElArr = frmtEl.split(' ')
curHeader = frmtElArr[0] frmtElArr[1].toUpperCase()
obj[curHeader] = []
}
else
{
obj[curHeader].push(el)
}
})
console.log(obj)
CodePudding user response:
(1) Start off by split()
ting with [
as the separator which should give you as many groups as there are in the string:
[ '', 'group a]\na\nb\nc\n', 'group b]\na\nd\nf' ]
(2) Use .filter()
to remove undesired empty strings:
[ 'group a]\na\nb\nc\n', 'group b]\na\nd\nf' ]
(3) Now use .map()
to transform each group using ]
or \n
as separators:
[ [ 'group a', '', 'a', 'b', 'c', '' ], [ 'group b', '', 'a', 'd', 'f' ] ]
(4) Use .filter()
to remove undesired empty strings:
[ [ 'group a', 'a', 'b', 'c' ], [ 'group b', 'a', 'd', 'f' ] ]
(5) Lastly use .reduce()
and Object.assign()
to convert each group into a key-value pair:
{ 'group a': [ 'a', 'b', 'c' ], 'group b': [ 'a', 'd', 'f' ] }
Please note that the fragment,
.split(' ').map((a,i) => i === 0 ? a : a.toUpperCase()).join('')
is what converts group a
into groupA
, etc
DEMO
let data = `[group a]
a
b
c
[group b]
a
d
f
[group c]
g
h
t`;
let obj = data
.split(/\[/)
.filter(v => v)
.map(v => v.split(/\]|[\r\n] /)
.filter(v => v))
.reduce((acc,val) =>
Object.assign(acc,
{[val[0].split(' ').map((a,i) => i === 0 ? a : a.toUpperCase()).join('')]:val.slice(1)}),{});
console.log( obj );