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

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.