Empresas
Empleos
  • Sobre nosotros
  • Soluciones
    • Publicación de vacantes
      Publica tu vacante y recibe candidatos calificados en 48h.
    • Evaluación de candidatos
      500+ pruebas técnicas y psicológicas, más anti-fraude.
    • Headhunting
      Búsqueda ejecutiva a la medida de principio a fin.
    • Nómina + EOR
      Dispersión de nómina y EOR en más de 15 países de LATAM.
  • Precios
  • Empleos

0

130
Vistas
How to parse an arbitrary mathematical expressions containing arrays in javascript

I want to store arbitrary mathematical expression with basic operations (+, -, *, /, ^, sqrt, grouping, etc…) and id placeholders as a string.

const json = {
  “formula”: “{{a45bc2a1-ed82-4ccd-a455-f7959e875aad}}+({{f6c2ef2b-a4fa-4cfb-b62d-d0d7c3e266d9}}*{{335563ad-a715-47b9-8e54-2b8553768168}})”
}

Ids are mapped to arrays such as:

const map = {
  “a45bc2a1-ed82-4ccd-a455-f7959e875aad”: [1, 2, 3, 4, 5],
  “f6c2ef2b-a4fa-4cfb-b62d-d0d7c3e266d9”: [10, 20, 30, 40, 50],
  “335563ad-a715-47b9-8e54-2b8553768168”: [1, 2, 3, 4, 5]
}

How can I achieve this? eval() doesn’t work with vectors and I don’t know how to parse arbitrary formula to do element-wise operations

Result should be:

[11, 42, 93, 164, 255]
about 4 years ago · Juan Pablo Isaza
3 Respuestas
Responde la pregunta

0

Since you're, in fact, developing a programming language, you'll going to need a compiler (=translate string expressions into an AST) and a runtime (=evaluate AST given inputs and predefined bindings). Here's some code to get you started. It only supports a limited grammar expression = term | term op expression and doesn't handle any errors:

// "compiler"

function parse(str) {
    return expr([...str])
}

function expr(chars) {
    let node = term(chars)
    if (chars.length)
        node = {
            op: chars.shift(),
            left: node,
            right: expr(chars)
        }
    return node
}

function term(chars) {
    let str = ''
    while (chars.length && chars[0].match(/\w/))
        str += chars.shift()
    return {value: str}
}

// "runtime"

ops = {
    '+': (a, b) => a + b,
    '-': (a, b) => a - b,
}

function evaluate(node, bindings) {
    if (node.value)
        return bindings[node.value]
    return eval_op(
        node.op,
        evaluate(node.left, bindings),
        evaluate(node.right, bindings))
}

function eval_op(op, left, right) {
    let fn = ops[op]
    return left.map((_, i) => fn(left[i], right[i]))
}

// demo

input = 'abc+def+xyz'
bindings = {
    'abc': [1, 2, 3],
    'def': [4, 5, 6],
    'xyz': [7, 8, 9],
}

ast = parse(input)
console.log('AST', ast)
res = evaluate(ast, bindings)
console.log('RESULT', res)

Of course, there's a lot more work involved to turn this sketch into real code. I'd suggest you learn a bit about formal grammars, parsers and parser generators.

about 4 years ago · Juan Pablo Isaza Denunciar

0

Loop over the array indexes, and replace the placeholders with the current index in the corresponding element of map. Then call eval().

let len = Object.values(json.formula)[0].length;
for (let i = 0; i < len; i++) {
    let formula = json.formula.replace(/{{([-\w]+)}}/g, (m, placeholder) => map[placeholder][i];
    console.log(eval(formula));
}
about 4 years ago · Juan Pablo Isaza Denunciar

0

I played around with this a while today and got a version working that does not require defining a formal AST, and only uses eval() to instantiate an arrow function that calculates each index of the output based on the input lists and an incrementing input index.

'use strict';
const json={
    formula: '{{a45bc2a1-ed82-4ccd-a455-f7959e875aad}}+({{f6c2ef2b-a4fa-4cfb-b62d-d0d7c3e266d9}}*{{335563ad-a715-47b9-8e54-2b8553768168}})'
}

const map = {
    'a45bc2a1-ed82-4ccd-a455-f7959e875aad': [1, 2, 3, 4, 5],
    'f6c2ef2b-a4fa-4cfb-b62d-d0d7c3e266d9': [10, 20, 30, 40, 50],
    '335563ad-a715-47b9-8e54-2b8553768168': [1, 2, 3, 4, 5]
}

function parseFormula (formula) {
    const template = /{{([^}]*)}}/;
    const idList = [];
    for (let i = 0; template.test(formula); i++) {
        idList.push(formula.match(template)[0].replace(/[{}]/g, ''));
        formula = formula.replace(template, `input[${i}][i]`);
    }
    return {idList, formula};
}

function calculateFormula(map, parsed) {
    const input = [];
    const result = [];
    const lambda = eval(`(input, i) => ${parsed.formula}`)
    parsed.idList.forEach(id => input.push(map[id]));
    for (let i = 0; i < input[0].length; i++) {
        result.push(lambda(input, i));
    }
    return result;
}

const parsed = parseFormula(json.formula);
console.log(parsed);
console.log(calculateFormula(map, parsed));

Output:

{
  idList: [
    'a45bc2a1-ed82-4ccd-a455-f7959e875aad',       
    'f6c2ef2b-a4fa-4cfb-b62d-d0d7c3e266d9',       
    '335563ad-a715-47b9-8e54-2b8553768168'        
  ],
  formula: 'input[0][i]+(input[1][i]*input[2][i])'
}
[ 11, 42, 93, 164, 255 ]
about 4 years ago · Juan Pablo Isaza Denunciar
Responde la pregunta
Encuentra empleos remotos

¡Descubre la nueva forma de encontrar empleo!

Top de empleos
Top categorías de empleo
Empresas
Publicar vacante Precios Comercial
Legal
Términos y condiciones Política de privacidad
© 2026 PeakU Inc. All Rights Reserved.
Andres GPT
Recomiéndame algunas ofertas
Necesito ayuda