Convert JS Array to a nested Object - javascript

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);

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}

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/)

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;
}

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);

Related

height chart series doesn't work in react js

I use height chart in my project but I have a problem with series I write function for series but in series section cant read my data and dra
const series = useMemo(() => {
const calcvolumeBuy = [];
const calcvolumeSell = [];
if (data) {
for (let i = 1; i < 5 + 1; i += 1) {
const obj = {};
obj.price = data['qd' + i];
obj.volume = data['po' + i];
calcvolumeBuy?.push(obj);
}
for (let i = 1; i < 5 + 1; i += 1) {
const obj = {};
obj.price = data['po' + i];
obj.volume = data['qo' + i];
calcvolumeSell?.push(obj);
}
}
return [
{
name: 'buy',
color: '#03a7a8',
data: calcvolumeBuy,
},
{
name: 'sell',
color: '#fc5857',
data: calcvolumeSell,
},
];
}, [data]);
so this is series how I use :
series: series,
w a chart this is my function I write for series

Javascript Recursion with helper function

I have this chunk of code and I want to print this out.
a
|->b
|->c
|->e
It works when I use
let spaceStr = " ".repeat(level) + "|->";
but not when I use the helper function getSpace.
It only prints the following:
a
|->b
I cannot figure out why. Can someone explain to me?
const obj =
{ name: 'a', children:
[ { name: 'b', children: [] }
, { name: 'c', children:
[ { name: 'e', children: [] }
]
}
]
}
function getSpace(level){
var str = '';
for (i=0; i < level; i++){
str += ' ';
}
str += '|->';
return str
}
function getPath(obj, level) {
let result = [];
let resultString = '';
let spaceStr = " ".repeat(level) + "|->";
// let spaceStr = getSpace(level);
if (obj.children.length === 0) {
return spaceStr+obj.name;
} else {
if (level === 0) {
result.push(obj.name);
} else {
result.push(spaceStr + obj.name);
}
for (i=0;i<obj.children.length;i++){
result.push(getPath(obj.children[i], level+1));
}
}
return result;
}
function printPath(result){
for (i=0;i<result.length;i++){
console.log(result[i]);
}
return
}
printPath(getPath(obj,0).flat());
By using i=0 in your loops, you're not scoping the variable i correctly to the loop. Instead, it will bubble up to the closest instance of that variable name (until it hits the global scope). Consider using let i = 0 in your loops to properly scope the variable. See the following functioning code:
const obj = {
"name": "a",
"children": [{
"name": "b",
"children": []
},
{
"name": "c",
"children": [{
"name": "e",
"children": []
}]
}
]
}
function getSpace(level){
var str = '';
for (let i = 0; i < level; i++){
str += ' ';
}
str += '|->';
return str
}
function getPath(obj, level) {
let result = [];
let resultString = '';
//let spaceStr = " ".repeat(level) + "|->";
let spaceStr = getSpace(level);
if (obj.children.length === 0) {
return spaceStr+obj.name;
} else {
if (level === 0) {
result.push(obj.name);
} else {
result.push(spaceStr + obj.name);
}
for (let i = 0;i<obj.children.length;i++){
result.push(getPath(obj.children[i], level+1));
}
}
return result;
}
function printPath(result){
for (let i = 0;i<result.length;i++){
console.log(result[i]);
}
return
}
printPath(getPath(obj,0).flat());

how to stop loop while using setTimeout function

const fruits = ['apple', 'mango', 'orange', 'date'];
let found = 0;
fruits.forEach((value, key) => {
if (found == 0) {
console.log("value", value)
setTimeout(() => {
if (value.length > 1) {
found = 1;
}
}, 200)
}
})
Stop loop when it get caught found=1 but after using setTimout it does not behave like this how to solve it
Does this what you want:
const fruits = ['apple', 'mango', 'orange', 'date'];
let found = 0;
for (var i = 0 ; i < fruits.length ; i++ ) {
const value = fruits[i];
if (value.length > 1) {
found = 1;
console.log("Founded", value)
break;
} else {
console.log("Value", value)
}
}
console.log("Found: ",found)

how to get the mentioned expected output from a object with nested objects

I have this data of objects ,
but unable to get expected output
we need to iterate on object children and print the name values in a particular order as given below
expected output :
kiran
vish
lav
mall
tried code :
let data = {
name: 'kiran',
children: [{
name: 'vish',
children: [{
name: 'lav',
children: []
},
{
name: 'mall',
children: []
}
]
}]
}
/* kiran
vish
lav
mall */
function indent(inputData) {
function indentHandler(inpData, level, output) {
if (!output) {
let output = '';
}
if (inpData.children.length) {
for (let i = 0; i < inpData.children.length; i++) {
level = level + 1;
console.log(addSpaces(level) + inpData.name + '\n');
indentHandler(inpData.children[i], level);
}
} else {
console.log(addSpaces(level) + inpData.name + '\n');
}
return output;
}
return indentHandler(inputData, 0, '');
}
function addSpaces(level) {
let outp = '';
for (let i = 0; i < level; i++) {
outp = outp + ' ';
}
return outp;
}
indent(data)
https://jsbin.com/yanogok/edit?js,console
please correct my program as I m unable to get correct output
Move your parent console.log out of loop
Do not change level in loop, just pass level + 1
let data = {
name: 'kiran',
children: [{
name: 'vish',
children: [{
name: 'lav',
children: []
},
{
name: 'mall',
children: []
}
]
}]
}
/* kiran
vish
lav
mall */
function indent(inputData) {
function indentHandler(inpData, level, output) {
if (!output) {
let output = '';
}
if (inpData.children.length) {
console.log(addSpaces(level) + inpData.name + '\n');
for (let i = 0; i < inpData.children.length; i++) {
indentHandler(inpData.children[i], level + 1);
}
} else {
console.log(addSpaces(level) + inpData.name + '\n');
}
return output;
}
return indentHandler(inputData, 0, '');
}
function addSpaces(level) {
let outp = '';
for (let i = 0; i < level; i++) {
outp = outp + ' ';
}
return outp;
}
indent(data)
function indent(data){
output = '';
return (function indentHandler(data, level){
output += addSpaces(level) + data['name'] + '\n';
if (data['children'].length === 0){
return output;
}
level += 1;
data['children'].forEach(function(child){
return indentHandler(child, level);
});
return output;
})(data, 0, '');
}
function addSpaces(level) {
let outp = '';
for (let i = 0; i < level; i++) {
outp = outp + ' ';
}
return outp;
}
indent(data)

Json data reading through Javascript

I am trying to read json data from website through JavaScript. Json looks like this:
{
"status" : "success",
"prices" : [
{
"market_hash_name" : "AK-47 | Aquamarine Revenge (Battle-Scarred)",
"price" : "11.38",
"created_at" : 1460116654
},
So, I got code:
if(pricelist.prices.market_hash_name == itemName) {
var price2 = Math.round(Number(pricelist.prices.market_hash_name[itemName].price) * 1000);
I know that I am doing something wrong here, could someone help me out?
EDIT: That Function is here:
function loadItems() {
$("#refresh-button").remove();
$("#loading").addClass("active");
$.getJSON("" + bot_sids[cur_bot], function(data) {
if (data.success) {
var i = 0;
var ready = true;
var invIndexes = [];
for (var index in data.rgInventory) {
invIndexes[i] = index;
i++;
}
i = 0;
$.getJSON("", function(pricelist) {
apricething = pricelist;
if (pricelist.status) {
for (id = 0; id < invIndexes.length; id++) {
var index = invIndexes[id];
var item = data.rgDescriptions[data.rgInventory[index].classid + "_" + data.rgInventory[index].instanceid];
if (item.tradable != 1) {
continue;
}
var itemName = item.market_hash_name;
var iconUrl = item.icon_url;
console.log(itemName);
for(i=0; i<pricelist.prices.length; i++){
if (pricelist.prices[i].market_hash_name == itemName) {
var price2 = Math.round(Number(pricelist.prices[i].market_hash_name.price) * 1000);
console.log(itemName);
console.log(price2);
if (price2 >= 1) {
prices2[itemName] = price2;
items[id] = {
name: itemName,
price: price2,
iconurl: iconUrl,
classid: data.rgInventory[index].classid,
id: index,
done: true
};
} else {
items[id] = {
done: true
};
}
} else {
items[id] = {
name: itemName,
price: 0,
iconurl: iconUrl,
classid: data.rgInventory[index].classid,
id: index,
done: false
};
}
}
}
finishedLoading();
}
});
According to your data structure, you need an iteration over prices.
var price2;
pricelist.prices.some(function (item) {
if (item.market_hash_name == itemName) {
price2 = Math.round(Number(item.price) * 1000);
return true;
}
});
Try this :
if(pricelist.prices[0].market_hash_name == itemName) {
var price2 = Math.round(Number(pricelist.prices[0].market_hash_name.price) * 1000);
Your mixing some things up here. prices is an array, but you are not accessing the elements of the array, but the whole array.
Then in the number calculation, you are trying to access market_hash_name as an array, which is a string.
So the following code will walk through your prices and calculate price2 if the names match.
for(var i=0; i<pricelist.prices.length; i++){
if (pricelist.prices[i].market_hash_name === itemName) {
var price2 = Math.round(Number(pricelist.prices[i].price) * 1000);
}
}

Categories