我正在尝试制作一个烹饪食谱计算器,它基本上可以抓取所有数字并将它们分开(到目前为止)。除了划分所有数字之外,还会将小数转换为分数。这个很重要。现在,当我运行循环以查找要替换的数字时,当行上的数字大于1时,我遇到问题。如果我输入1 egg and 2 cups of milk
并告诉它除以2,它将执行此操作:
first iteration:
find: 1 and replace 1 with 1/2
result: 1/2 egg and 2 cups of milk
second iteration:
find: 2 and replace 2 with 1
result: 1/1 egg and 2 cups of milk
如果您理解正确,我现在会1/1 2
。为什么?因为在第二次迭代中,它会找到2
并将其替换为1
。我基本上需要说:
if(number != fraction)
replace number;
我如何从我的代码中做到这一点?
JSFiddle:http://jsfiddle.net/fgzt82yk/8/
我的循环:
for(i = 0; i < content.length; i++) {
//Finds numbers on the line
var number = content[i].match(regex);
//number == null if the line is empty
if(number != null) {
//There can be more than 1 number on each line, create a new loop
for(j = 0; j < number.length; j++) {
//Turns fractions into decimals
var evalNumber = eval(number[j]);
//Divides the number
var divided = parseFloat(evalNumber / selection);
//We need some kind of precision, so we won't get 0.1666667 and so on
var precision = selection;
if(precision == 2) {
precision = 0;
}
//Turns our decimal into a fraction (or a whole-number)
var newNum = Math.fraction(divided.toString(), precision);
//Replaces the original number from the content[i] (whole line) with the new number/fraction
content[i] = content[i].replace(number[j], newNum);
}
}
}
添加了评论,以便更清楚地说明每行的含义。这是困扰我的最后一行..我确定。
我基本上在寻找一种更好的方法将数学应用于所有数字(小数,分数,混合数等等)。到目前为止,它有点工作,但我相信有人有更好的方法做到这一点!谢谢你的期待!
答案 0 :(得分:7)
对于您的用例,我认为解决方案不是要找出如何不分割已经分割的数字,而是要一次性替换所有数字。
例如,如果你有一个要求的食谱:
并且您希望将事情减半,最后可能会将12
替换为6
,然后在该传递上再次替换6
。 (是的,你可以做到最大到最小的数字,但是你需要一个通行证来订购所有的数字。不必要的复杂性。)
如果您还要使用正则表达式,我建议您执行类似
的操作function fractionize(n, d) {
var gcd = (function gcd(a, b) {
if ( ! b) {
return a;
}
return gcd(b, a % b);
})(n ,d);
return d == gcd ? n / d : (n > d ? Math.floor(n / d) + ' ': '') + (n % d / gcd) + '/' + (d / gcd);
}
function decimalize(decimal, precision) {
var power = Math.pow(10, precision);
return Math.round(decimal * power) / power;
}
function scaleRecipe(recipe, multiply, divide) {
return recipe.replace(/((\d*\.\d+)|((\d+)\s+)?(\d+)(\s*\/\s*(\d+))?)/g, function(_, _, decimal, _, wn, n, _, d) {
d = d || 1;
return decimal ? decimalize(decimal * multiply / divide, decimal.match(/\d/g).length) : fractionize(((wn || 0) * d + parseInt(n)) * multiply, divide * d);
});
}
例如:
scaleRecipe('12 eggs, 6 cups of water, 13 chickens, 4 lb rice, 17 tsp vanilla, 60g sugar, 3/4 cups chocolate chips, 2/3 lb beef, 1/5 oz secret sauce, 3 1 / 2 teaspoons salt', 1, 6)
会给你
"2 eggs, 1 cups of water, 2 1/6 chickens, 2/3 lb rice, 2 5/6 tsp vanilla, 10g sugar, 1/8 cups chocolate chips, 1/9 lb beef, 1/30 oz secret sauce, 7/12 teaspoons salt, 0.1 lb ham, 0.027 oz honey, 0.35 pint blueberries"
并且相同的食谱/8
会给你
"1 1/2 eggs, 3/4 cups of water, 1 5/8 chickens, 1/2 lb rice, 2 1/8 tsp vanilla, 7 1/2g sugar, 3/32 cups chocolate chips, 1/12 lb beef, 1/40 oz secret sauce, 7/16 teaspoons salt, 0.1 lb ham, 0.02 oz honey, 0.26 pint blueberries"
您还可以使用其他逻辑来减少分数(请参阅:JS how to find the greatest common divisor)并格式化为混合数字(分别取整数和余数部分)。
复数可能是你想要考虑的另一个方面,但英语是一种棘手的语言,有许多边缘情况。 :)
答案 1 :(得分:0)
它似乎是String.prototype.replace()
的工作 - 正是你已经使用过的那个。
只需将正则表达式作为第一个参数传递,然后将转换函数作为第二个参数传递,这样您就可以一次更改所有数字 - 您不必担心数字会受到两次影响