0

I have code that loops through a string to make a sort of tree in the form of a JSON Object. Every time a certain character is reached, the array should go down a level. The only way I have been able to accomplish this is with eval(). I recreate the index necessary to go down a row in a custom push function by generating something like this JSON_OBJECT[2][8].push(value). eval() is not only a security issue but is also pretty slow.

Below I have a similar script where I used a space as the certain character. When running 1,000 randomly generated filler words the script takes ~1000ms. By just removing the eval and replacing it with a json.push(value) the script takes at most 3ms.

I know that eval() wasn't using all of the time, but it has to be a big part. Speed is a big factor in the script and a 1,000 words is not very far off from what this script will be processing. Is there a way I can do this without eval()?

Here's the script

var string = 'lorem ipsum dolor sit amet consectetur adipiscing elit ut',
    json = [],
    levelIndex = [];

for (let i = 0; i < string.length; i++) {
  
  if (string[i - 1] == ' ') {
    levelIndex.push(deepestLength() - 1);
  }
  
  if (string[i] == ' ') {
    customPush([]);
  } else {
    customPush(string[i]);
  }
}

function customPush(value) {
  let path = '';

  for (let i = 0; i < levelIndex.length; i++) {
    path += '[' + levelIndex[i] + ']';
  }
  
  eval('json' + path + '.push(' + JSON.stringify(value) + ')');  
}

function deepestLength() {
  let deepest = json;
  
  for (let i = 0; i < levelIndex.length; i++) deepest = deepest[levelIndex[i]];
  
  return deepest.length;
}

document.write('Completed Array: <br>' + JSON.stringify(json));

1

3 Answers 3

1

Sure thing. Try this:

function x(string, marker) {
  var root = [];
  var current = root;
  for(var i = 0; i < string.length; i++) {
    if(string[i] === marker) {
      var newCurrent = [];
      current.push(newCurrent);
      current = newCurrent;
    } else {
      current.push(string[i]);
    }
  }
  return root;
}
var result = x('lorem ipsum dolor sit amet consectetur adipiscing elit ut', " ");
console.log(result);
console.log(JSON.stringify(result));

Sign up to request clarification or add additional context in comments.

1 Comment

Thanks. I knew that there had to be a better way. My first thought was to do it the way you did, but I assumed that assigning a current wouldn't update the root once changed.
1

you can try this approach:

function deep(nodes, separator) {
  return nodes
    .split(separator)
    .reduceRight((result, element) => {
      result.unshift(...element.split(""));
      return [ result ];
    }, []);
}

var result = deep("lorem ipsum dolor sit amet consectetur adipiscing elit ut", " ");
console.log(JSON.stringify(result));

1 Comment

Thanks for your answer. The code is super concise but it seems significantly slower than AKX's answer.
0

Late to the party, but this works using recursion, and the fact that arrays are passed by reference, not value.

var string = "Lorem ipsum dolor sit amet consectetur adipiscing elit ut";
let myjson = [];

let recursiveDrillandAppend = (array, value) => {
  if (!Array.isArray(array)) return true;

  if (recursiveDrillandAppend(array[array.length - 1], value))
    array.push(value);
};

for (let i = 0; i < string.length; i++) {
  if (string[i] === " ") recursiveDrillandAppend(myjson, []);
  else recursiveDrillandAppend(myjson, string[i]);
}

document.write("Completed Array: <br>" + JSON.stringify(myjson) + "<br>");

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.