0

Is there any RegEx which can test this scenario.

  1. String with comma separated number where left number should be less than right. Correct example: 1,2,3 4,10,20 Incorrect example: 3,2,1 4,1,20

  2. String can have - separator like 1-25, where left should be smaller than right and the string should not have number between this range.

Correct example: 1-50,51,52,55-60 1,2,3-10,12,20 Incorrect example: 1-50,49,20,60 2,3,1-10,11

Should I write separate function for this?

Thanks

7
  • 2
    You could write a regex for that but it's going to be virtually unmaintainable. Commented Mar 8, 2019 at 11:56
  • 1
    The idea of a regex is not to validate logic inside expressions, but only expressions itself. This means that the part "left should be smaller than right" is not a correct use case for a regex. In my opinion, you should validate the regex first (the part that states that it is a comma separated list of numbers, with the posibility of ranges), and then, in a second iteration, validate the logic inside your string. Commented Mar 8, 2019 at 12:00
  • it's as @jfc says for example filter for each number and add it to a list or something like it and then go through it and look if the next number is bigger than the one before Commented Mar 8, 2019 at 12:03
  • You can't do that with Regular Expressions. Simply not possible without utilising a programming language (JS here). Commented Mar 8, 2019 at 12:07
  • @revo I disagree slightly - you could do that with regex. Here is a sample /1-[2-9]|2-[3-9]|3-[4-9]|4-[5-9]|5-[6-9]|6-[7-9]|7-[89]|8-9/ - that validates if you have only two single-digit numbers on either side of a - sign and the left one is smaller than the right one. The complexity of creating a regex for anything more than two single-digit numbers explodes, so it's extremely hard to do it by hand. So, technically the task is possible. It still shouldn't be attempted in any serious application. And I apologise for causing any headaches and/or vomit with that regex. Commented Mar 8, 2019 at 12:35

2 Answers 2

2

Here's a non-regex solution. You could split the numbers at , and then sort them based on their numerical value. Use the Max value if the value is a range. Then join the sorted array. Check if the resulting string is same as the original string

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"))

Sign up to request clarification or add additional context in comments.

9 Comments

It seems like legit. Will run it with other test cases. Thanks BTW
above function did not pass 1,3,1-12 this test. As it's failing to check if 1 already exists or not in the string. But i learn new way to write function with this syntax. Thanks for that
@PraveenRawat The examples you have given in the question don't have overlapping numbers. The implementation uses the max value for comparing when a range is given. getMaxValue function can be changed depending on how you want to handle ranges. Whether you want to use min value or max value. How should 1,3,1-12 be sorted? The current implementation keeps them in that same order because 12 is bigger than 1 and 3
exactly its not sorted and function should fail to do so. But you are right I need to modify it as per my need. Accepting this as answer and will update mine when its done.
@PraveenRawat So, what is the correct order for 1,3,1-12?
|
1

Using a regex for this task would be really difficult. I think a better approach is to do it using 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']));

1 Comment

thanks man for helping. Will run the same with other test cases.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.