skip to Main Content

Having this as input '<apple, <pear>>, <orange, <apple>, <cherry>, banana>, <banana, <pear>, <orange>>' having in mind that whatever is inside angle brackets is considered a node, so the output should be:
['<apple, <pear>>', '<orange, <apple>, <cherry>, banana>', '<banana, <pear>, <orange>>']

I’ve tried regex and split like this

const regexBycomma = /([^,<]*(?:<[^>]*>[^,<]*)*),?/g;
str.split(regexBycomma);

with not good results, also many algorithms like this one:

function getParentNodes(input) {
  const nodes = input.match(/<[^<>]+>/g); // Extract all nodes from the input
  const parentNodes = [];
  let currentParentNode = '';

  for (const node of nodes) {
    if (currentParentNode === '') {
      currentParentNode = node;
    } else if (node.startsWith(currentParentNode)) {
      currentParentNode += ',' + node;
    } else {
      parentNodes.push(currentParentNode);
      currentParentNode = node;
    }
  }
  
  if (currentParentNode !== '') {
    parentNodes.push(currentParentNode);
  }

  return parentNodes;
}

2

Answers


  1. Here the idea is to track how deep you are in to the nodes by adding to the depth when encountering a < and reducing it when encounting a >. When the depth becomes zero start a new string.

    const nodes_string = '<apple, <pear>>, <orange, <apple>, <cherry>, banana>, <banana, <pear>, <orange>>';
    const nodes_string2 = 'doughnut, <apple, <pear>>, muffin, crumpet, <orange, <apple>, <cherry>, banana>, <banana, <pear>, <orange>>, pie';
    
    const clean_text_nodes = (node) =>
      node.startsWith('<') ?
        node :
        node
          .split(',')
          .map( (str) => str.trim() )
          .filter( (str) => str !== '' );
    
    const get_top_nodes = (nodes_string) => {
      let depth = 0;
      const result = [''];
      
      for(const char of nodes_string) {
        if(char === '<') {
          if(depth === 0) result.push('');
          depth++;
        }
        
        result[result.length - 1] += char;
        
        if(char === '>') {
          depth--;
          if(depth === 0) result.push('');
        }
      }
      
      return result.flatMap(clean_text_nodes);
    };
    
    console.log(get_top_nodes(nodes_string));
    console.log(get_top_nodes(nodes_string2));
    Login or Signup to reply.
  2. You might just naively count opened and closed brackets and push "nodes" to the result:

    const parse = str => {
      const result = [];
      let sub = '',
        opened = 0,
        closed = 0;
      for (const s of str) {
        if (s === '<') ++opened;
        else if (s === '>') ++closed;
        if (opened > 0) {
          sub += s;
          if (opened === closed) {
            opened = closed = 0;
            result.push(sub);
            sub = '';
          }
        }
      }
      return result;
    }
    
    console.log(parse('<apple, <pear>>, <orange, <apple>, <cherry>, banana>, <banana, <pear>, <orange>>'))
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search