【问题标题】:RegEx for range and increment checkRegEx 用于范围和增量检查
【发布时间】:2019-03-08 11:52:12
【问题描述】:

是否有任何正则表达式可以测试这种情况。

  1. 用逗号分隔的数字字符串,其中左边的数字应该小于右边的数字。 正确示例:1,2,3 4,10,20 错误示例:3,2,1 4,1,20

  2. 字符串可以有 - 分隔符,如 1-25,其中左侧应小于右侧,字符串不应在此范围内包含数字。

正确示例:1-50,51,52,55-60 1,2,3-10,12,20 错误示例:1-50,49,20,60 2,3,1-10,11

我应该为此编写单独的函数吗?

谢谢

【问题讨论】:

  • 可以为此编写一个正则表达式,但它几乎无法维护。
  • 正则表达式的想法不是验证表达式内部的逻辑,而只是验证表达式本身。这意味着“左边应该小于右边”的部分不是正则表达式的正确用例。在我看来,您应该首先验证正则表达式(声明它是逗号分隔的数字列表的部分,具有范围的可能性),然后在第二次迭代中验证字符串中的逻辑。
  • 正如@jfc 所说,例如过滤每个数字并将其添加到列表或类似的东西中,然后查看下一个数字是否大于前一个数字
  • 你不能用正则表达式来做到这一点。如果不使用编程语言(此处为 JS),根本不可能。
  • @revo 我有点不同意 - 你可以用正则表达式做到这一点。这是一个示例/1-[2-9]|2-[3-9]|3-[4-9]|4-[5-9]|5-[6-9]|6-[7-9]|7-[89]|8-9/ - 它验证您是否在- 符号的两侧只有两个单位数字,并且左边的数字小于右边的数字。为超过两个个位数的数字创建正则表达式的复杂性爆炸式增长,因此手动完成非常困难。所以,技术上这个任务是可能的。它仍然不应该在任何严肃的应用程序中尝试。对于使用该正则表达式引起任何头痛和/或呕吐,我深表歉意。

标签: javascript regex


【解决方案1】:

这是一个非正则表达式的解决方案。您可以 split , 的数字,然后根据它们的数值 sort 它们。如果值是一个范围,则使用 Max 值。然后join 排序后的数组。检查结果字符串是否与原始字符串相同

const getMaxValue = str => str.includes("-") ? +str.split("-")[1] : +str;

const checkInOrder = str => str === str.split(",")
                                  .sort((a,b) => getMaxValue(a) - getMaxValue(b))
                                  .join(",")

console.log(checkInOrder("1,2,3,4,10,20"))
console.log(checkInOrder("3,2,1,4,1,20"))
console.log(checkInOrder("1-50,51,52,55-60"))
console.log(checkInOrder("1,2,3-10,12,20"))
console.log(checkInOrder("1,2,3-10,12,20"))
console.log(checkInOrder("1-50,49,20,60,2,3,1-10,11"))

【讨论】:

  • 这似乎是合法的。将与其他测试用例一起运行。谢谢顺便说一句
  • 以上函数没有通过 1,3,1-12 这个测试。因为它无法检查 1 是否已经存在于字符串中。但是我学习了用这种语法编写函数的新方法。谢谢你
  • @PraveenRawat 您在问题中给出的示例没有重叠的数字。当给定范围时,该实现使用最大值进行比较。 getMaxValue 函数可以根据您处理范围的方式进行更改。是否要使用最小值或最大值。 1,3,1-12 应该如何排序?当前的实现使它们保持相同的顺序,因为12 大于13
  • 正是它没有排序,函数应该不能这样做。但你是对的,我需要根据我的需要修改它。接受这个作为答案,完成后会更新我的。
  • @PraveenRawat 那么,1,3,1-12 的正确顺序是什么?
【解决方案2】:

使用正则表达式来完成这项任务真的很困难。我认为更好的方法是使用 JavaScript:

const isValid = arr => {
  const items = [];
  const ranges = [];
  const inRange = (range, x) => x >= range.start && x <= range.end;
  
  for (let i = 0; i < arr.length; ++i) {
    const x = +arr[i];
    const rangeParts = /(\d+)\s*-\s*(\d+)/.exec(arr[i]);
    if (rangeParts) {
      const range = { start: +rangeParts[1], end: +rangeParts[2] };
 
      const validRange = range.start < range.end &&
        ranges.every(r => range.start > r.end || range.end < r.start);
      if (!validRange) return false;
      
      const itemsInRange = items.some(item => inRange(range, item));
      if (itemsInRange) return false;
      
      ranges.push(range);
    }
    const inRanges = ranges.some(r => inRange(r, x));
    if (inRanges) return false;

    if (i > 0 && items[items.length-1] >= x) return false;
    
    items.push(x);
  }
  return true;
};

console.log(isValid(['1', '2', '3', '4']));
console.log(isValid(['1', '2', '3', '4', '5-7']));
console.log(isValid(['1', '2', '3', '4', '5-7', '1-3']));
console.log(isValid(['1', '2', '3', '4', '5-7', '7-8']));
console.log(isValid(['1', '2', '3', '4', '5-7', '8-10']));
console.log(isValid(['1', '20', '3', '4', '5-7', '8-10']));

【讨论】:

  • 感谢人的帮助。将与其他测试用例运行相同。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2015-05-03
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2010-11-12
相关资源
最近更新 更多