Reputation: 13
What is the best way to convert:
['[Title A]','child A','child B', '[Title B]', 'child C', 'child D']
to:
{
0: {
'title': 'Title A',
'children': ['child A', 'child B']
}
1: {
'title': 'Title B',
'children': ['Child C', 'Child D']
}
}
I have this so far which checks on the presence of brackets [] and I tried to add this to an object with a dynamic index which increments during a for loop every time a title with brackets is found:
let index = 0;
let listObject = {};
for (const listItem of listItems) {
const titleValue = listItem.match(/\[(.*?)\]/);
if (titleValue) {
++index;
listObject[index].title = titleValue[1];
} else {
listObject[index].children = [listItem];
}
}
console.log(listObject);
Upvotes: 1
Views: 128
Reputation: 343
For the sake of simplicity let's first make an array of objects:
const res = arr.reduce((acc, cur) => {
const titleValue = cur.match(/\[(.*?)\]/)
titleValue ?
acc.push({
title: cur,
children: []
}) :
acc[acc.length - 1].children.push(cur)
return acc
}, [])
Now you can use the spread operator
to have the nested object:
{...res}
Upvotes: 1
Reputation: 420
const array = ['[Title A]','child A','child B', '[Title B]', 'child C', 'child D'];
let objToPush = {};
let objToSend = {};
array.map((d) => {
if (/^\[[^\]]+\]$/.test(d)) {
if (Object.keys(objToPush).length > 0) {
objToSend[Object.keys(objToSend).length] = { ...objToPush };
objToPush = {};
}
objToPush.title = d.substring(1, d.length - 1);
} else {
objToPush.children = objToPush.children ? [...objToPush.children, d] : [d]
}
});
objToSend[Object.keys(objToSend).length] = { ...objToPush };
console.log('objToPush', objToSend);
it worked for me (JSFiddle https://jsfiddle.net/wepbzdfL/48/)
Upvotes: 0
Reputation: 3683
I don't know if it's the "best" way, but this is my solution:
const array = [
"[Title A]",
"child A",
"child B",
"[Title B]",
"child C",
"child D"
];
let index = -1;
const res = array.reduce((acc, curr) => {
if (/^\[[^\]]+\]$/.test(curr)) {
acc = {
...acc,
[++index]: { title: curr.substring(1, curr.length - 1), children: [] }
};
} else {
acc[index].children = [...acc[index].children, curr];
}
return acc;
}, {});
console.log(res);
Upvotes: 0
Reputation: 1574
Just updated yours so the logic is sound. Can see what you tried.
Read up on creating new objects and arrays in JS, and when you can add to them.
let listItems = ['[Title A]', 'child A', 'child B', '[Title B]', 'child C', 'child D'];
let index = 0;
var listObject = {};
for (const listItem of listItems) {
const isTitle = listItem[0] == "[" && listItem[listItem.length - 1] == "]"
if (isTitle) {
++index;
listObject[index] = {
title: listItem.substring(1, listItem.length -1),
children: [] //Create Array
}; //Create Object
} else {
listObject[index].children.push(listItem); //Add to children array
}
}
console.log(listObject);
To add on why I used an index lookup, instead of regex,
Run this:
var testArray = [];
var arrayCount = 20000000;
var regexMatch = /\[(.*?)\]/;
for (var i = 0; i < arrayCount; i++) {
testArray.push("[" + makeid(Math.round(Math.random() * 10)) + "]")
}
console.log(testArray.length);
var start = new Date();
console.log(start.toString());
for (var i = 0; i < arrayCount; i++) {
var testItem = testArray[i];
if (testItem.match(regexMatch)) {
} else {
}
}
console.log("regex took " + (new Date().getTime() - start.getTime()) / 1000 + " seconds");
start = new Date();
for (var i = 0; i < arrayCount; i++) {
var testItem = testArray[i];
if (testItem[0] === "[" && testItem[testItem.length - 1] === "]") {
} else {
}
}
console.log("index lookup took " + (new Date().getTime() - start.getTime()) / 1000 + " seconds");
function makeid(length) {
var result = '';
var characters = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789';
var charactersLength = characters.length;
for (var i = 0; i < length; i++) {
result += characters.charAt(Math.floor(Math.random() * charactersLength));
}
return result;
}
Upvotes: 0