问题描述
有没有办法在javascript中解析字符串中的数学表达式?例如,假设我想要生成字符串汤姆有2个苹果,露西有3个苹果。他们一起有5个苹果,但我希望能够替换变量。我可以用字符串替换来做到这一点:
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');
然而,如果不是使用变量Z,我会使用X + Y会更好。现在,我也可以为X + Y执行字符串替换并将其替换为正确的值,但在尝试处理我可能想要执行的所有可能的字符串计算时,这将变得混乱。我想我正在寻找一种方法来实现这个目标:
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.
感谢您的帮助。
推荐答案
没有直接的内置方式(好吧,好吧,也许有 —见下文),但如果你使用替换
函数的回调功能,其中替换可以是函数而不是字符串(返回值是替换的),你可以相当容易地实现它。
There's no direct, built-in way (well, okay, perhaps there is — see below), but if you use the callback feature of the replace
function, where the replacement can be a function rather than a string (the return value is what's substituted in), you can implement this fairly easily.
例如,假设您为占位符使用Ruby符号#{xyz}
。这段代码循环遍历:
For instance, suppose you use the Ruby notation #{xyz}
for your placeholders. This code loops through those:
var mappings, str;
str = "One #{X} three #{Y} five";
mappings = {
"X": 2,
"Y": 4
};
str = str.replace(/\#\{([^#]+)\}/g, function(match, key) {
var result;
result = mappings[key];
/* ...processing here */
return result;
});
结果字符串是一个2 3 4 5
,因为#{X}
和#{Y}
已通过查找替换。您可以查看密钥,看看它是否是表达式,需要进行评估而不是简单地查找。评估是您的实际工作所在。
The resulting string is One 2 three 4 five
, because #{X}
and #{Y}
have been replaced via lookup. You can look at the key and see whether it's an expression and needs to be evaluated rather than simply looked up. That evaluation is where your real work comes in.
现在,您可以使用与
和 eval
实现表达式支持;将 result = mapping [key];
上面的行更改为:
Now, you could use with
and eval
to achieve expression support; change the result = mapping[key];
line above to this:
with (mappings) {
result = eval(key);
}
如果你输入字符串One#{X三个#{Y}五个#{X + Y * 2}
进入,结果是一个2三个4五个10
—因为 2 + 4 * 2
= 10.
If you feed the string "One #{X} three #{Y} five #{X + Y * 2}"
into that, the result is One 2 three 4 five 10
— because 2 + 4 * 2
= 10.
这是因为带
将给定对象粘贴在作用域链的顶部,因此在解析非限定引用(例如 X
)时会检查第一件事,并且 eval
执行Javascript代码 —所以可以评估表达式 —并且在它被称为的范围内神奇地这样做。但要注意;正如埃里克指出的那样,并非所有运算符在各种表达形式中都是相同的,特别是Javascript将 ^
解释为按位异或,而不是强大的 。 (它没有指数运算符;你必须使用 Math.pow
。)
That works because with
sticks the given object on top of the scope chain, so it's the first thing checked when resolving an unqualified reference (like X
), and eval
executes Javascript code — and so can evaluate expressions — and magically does so within the scope in which it's called. But beware; as Eric pointed out, not all operators are the same in various forms of expression, and in particular Javascript interprets ^
to mean "bitwise XOR", not "to the power of". (It doesn't have an exponent operator; you have to use Math.pow
.)
但你需要要非常小心这一点,与
和 eval
(每个都以他们自己的方式)可能会有问题。但与
的主要问题在于,如果你做了一项任务,很难说某些事情来自哪里或者去哪里,你不是; eval
的主要问题来自于使用它来解释你无法控制的字符串。只要你保持安全措施并且知道这些问题...
But you need to be very careful about that sort of thing, both with
and eval
(each in their own way) can be problematic. But the main issues with with
are that it's hard to tell where something comes from or where it will go if you do an assignment, which you're not; and the main issues with eval
come from using it to interpret strings you don't control. As long as you keep safeguards in place and are aware of the issues...
将其归结为函数:
function evaluate(str, mappings) {
return str.replace(/\#\{([^#]+)\}/g, function(match, key) {
var result;
with (mappings) {
result = eval(key);
}
return result;
});
}
alert(evaluate(
"The expression '(#{X} + #{Y}) * 2' equals '#{(X + Y) * 2}'",
{"X": 2, "Y": 4}
)); // alerts "The expression '(2 + 4) * 2' equals '12'"
alert(evaluate(
"The expression '(#{X} + #{Y}) * 2' equals '#{(X + Y) * 2}'",
{"X": 6, "Y": 3}
)); // alerts "The expression '(6 + 3) * 2' equals '18'"
这篇关于Javascript字符串替换为计算的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!