views:

68

answers:

3

Is there a way to resolve mathematical expressions in strings in javascript? For example, suppose I want to produce the string "Tom has 2 apples, Lucy has 3 apples. Together they have 5 apples" but I want to be able to substitute in the variables. I can do this with a string replacement:

string = "Tom has X apples, Lucy has Y apples. Together they have Z apples";
string2 = string.replace(/X/, '2').replace(/Y/, '3').replace(/Z/, '5');

However, it would be better if, instead of having a variable Z, I could use X+Y. Now, I could also do a string replace for X+Y and replace it with the correct value, but that would become messy when trying to deal with all the possible in-string calculations I might want to do. I suppose I'm looking for a way to achieve this:

string = "Something [X], something [Y]. Something [(X+Y^2)/(5*X)]";

And for the [_] parts to be understood as expressions to be resolved before substituting back into the string.

Thanks for your help.

+1  A: 

The only way I can think of to achieve this would be a templating engine such as jTemplates. Also see the answers to this SO question.

Marcelo Cantos
+4  A: 
T.J. Crowder
That is very nice - a lot shorter than I'd expect. +1
Kobi
Nice of W3Schools not to document that particular feature of `replace`... http://www.w3schools.com/jsref/jsref_replace.asp
Eric
@Eric: Yeah, w3schools is convenient, but not reliable, if you follow me. MDC (https://developer.mozilla.org/En) is usually pretty good (they're having system problems at the moment). I usually just search on the function name plus either "mdc" or "msdn" (depending on whether I need to check IE quirks).
T.J. Crowder
Perfect, thanks very much.
Chris
+1  A: 

Nice question:

function substitutestring(str,vals)
{
    var regex = /\[[^\]]*\]/gi;
    var matches = str.match(regex);
    var processed = [];

    for(var i = 0; i<matches.length; i++)
    {
        var match = matches[i];
        processed[match] = match.slice(1,-1);

        for(j in vals)
        {
            processed[match] = processed[match].replace(j,vals[j]);
        }

        processed[match] = eval("("+processed[match]+")");
    }

    for(var original in processed)
    {
        str = str.replace(original,processed[original]);
    }
    return str;
}

document.write(
    substitutestring(
        "[x] + [y] = [x+y]",
        {"x": 1, "y": 2}
    )
);
Eric