JavaScript计算错误超过100

时间:2018-06-29 15:11:04

标签: javascript

我有一个针对quantity range: price数组检查数字(数量)的功能

var data = {
  "1 - 4": " $4.25 ",
  "10 - 24": " $3.25 ",
  "25 - 49": " $3.04 ",
  "5 - 9": " $3.51 ",
  "50+": " $2.84 "
}

function get_price(arr, val) {
  var price = Object.keys(arr).reduce((a, c) => {
    var s = c.trim();
    if (/\d+\-\d+/.test(s)) {
      var range = s.split("-");
      if (val >= parseInt(range[0]) && val <= parseInt(range[1])) {
        a = arr[c];
      }
    } else {
      s = s.replace(/\D/g, "");
      if (val >= s) {
        a = arr[c];
      }
    }
    return a;
  }, 0);
  return price;
}

问题是,如果数字大于50但小于100,则表示计算正确;超过100,则无法看到50+并使用该价格。

感谢您的帮助!

3 个答案:

答案 0 :(得分:5)

使用字符串作为对象的键,可以很好地工作:

const range = {
  "1-4": " $4.25 ",
  "10-24": " $3.25 ",
  "25-49": " $3.04 ",
  "5-9": " $3.51 ",
  "50+": " $2.84 "
}

有关property accessors的更多信息:

  

在此代码中,属性必须是有效的JavaScript标识符,即,一个字母数字字符序列,还包括不能以数字开头的下划线("_")和美元符号("$")。 。例如,object.$1有效,而object.1无效。

     

-MDN Web docs

演示:

function get_price(arr, val) {
  var price = Object.keys(arr).reduce((a, c) => {
    var s = c.trim();
    if (/\d+\-\d+/.test(s)) {
      var range = s.split("-");
      if (val >= parseInt(range[0]) && val <= parseInt(range[1])) {
        a = arr[c];
      }
    } else {
      s = s.replace(/\D/g, "");
      if (val >= s) {
        a = arr[c];
      }
    }
    return a;
  }, 0);
  return price;
}

const range = {
  "1-4": " $4.25 ",
  "10-24": " $3.25 ",
  "25-49": " $3.04 ",
  "5-9": " $3.51 ",
  "50+": " $2.84 "
}

console.log(get_price(range, 60))
console.log(get_price(range, 500))

答案 1 :(得分:1)

仅当您将字符串作为参数val传递给get_price时,您的代码才会起作用,因为它将对假设"100" > "50"之间的字符串进行比较,并且将失败。

确定要转换为数字

if (+val >= +s) {
    a = arr[c];
}

if (+val >= parseInt(range[0]) && +val <= parseInt(range[1])) {
    a = arr[c];
}

答案 2 :(得分:0)

我有一些不同的方法。我假设范围列表很可能会被重用。此解决方案使用的函数将'25 - 49'转换为{start: 25, end: 49},并使用该函数创建对象数组,例如{start: 25, end: 49, value: '$3.04'}。然后,我返回一个在该数组上关闭的函数,该函数接受一个价格并返回包含该价格的第一个范围的值。

这具有不连续解析范围字符串的优点(可能很小)。更重要的是,它将问题分解成几个可重用的部分。 makeRange可能在项目中的其他地方重用,findByRange也可能被重用。特定于当前需求的唯一部分是getPrice,这变得相当明确。

const makeRange = (desc, match = '') => 
  ((match = desc.match(/(\d+)\s*\-\s*(\d+)/)) && match && {start: Number(match[1]), end: Number(match[2])})
    || ((match = desc.match(/(\d+)\s*\+/)) && match && {start: Number(match[1]), end: Infinity})
    || ((match = desc.match(/<\s*(\d+)/)) && match && {start: -Infinity, end: Number(match[1]) - 1})
    || {start: NaN, end: NaN}


const findByRange = rangeValues => {
  const ranges = Object.keys(rangeValues).map(
    key => Object.assign({value: rangeValues[key]}, makeRange(key))
  ).sort((a, b) => a.start - b.start) // sorting mostly for cleanliness
  
  return val => {
    const range = ranges.find(range => range.start <= val && val <= range.end)
    return range ? range.value : false // or throw an exception, or use default
  }
}


const getPrice = findByRange({
  '< 5'    : ' $4.25 ',  // could also be '1 - 4'
  '5-9'    : ' $3.51 ',
  '10-24'  : ' $3.25 ',
  '25-49'  : ' $3.04 ',
  '50+'    : ' $2.84 '
});

[3, 7, 16, 42, 57, 143].forEach(
  n => console.log(`${n} --> ${getPrice(n)}`)
)