0
votes

Expression régulière pour faire correspondre un nombre répété de valeurs dans .net

Étant donné une plage de nombres de 1 à 30, un utilisateur est autorisé à sélectionner n'importe quel nombre de valeurs sans répétition entre 1 et 30, j'essaie d'écrire une expression régulière pour trouver les entrées valides et invalides.

var input = "1,12,30";
Regex regex = new Regex("([1-3][1-1],[1-3][1-1])+");
if(regex.IsMatch(input))
{
  Console.WriteLine("Input is in correct format");
}

Par exemple: 4,78,6 n'est pas valide
2,6,24 est valide

Que dois-je changer mon expression régulière en tant que?


4 commentaires

une regex ne serait pas le meilleur outil pour ce travail.


Vous pouvez utiliser input.Split (','). All (x => Int32.Parse (x)> 0 && Int32.Parse (x) <31)


sans répétition entre 1 et 30 , donc chaque numéro une seule fois?


Diriez-vous que 30,29,28 est valide même s'ils ne sont pas dans le bon ordre? Et est-ce que 1,1,10 serait invalide parce qu'il y a des instances dupliquées de 1 ?


4 Réponses :


4
votes

Regex est un outil de traitement de texte pour faire correspondre les modèles dans les langues régulières. Il est très faible en matière de sémantique. Il ne peut pas identifier la signification dans la chaîne donnée. Comme dans votre condition donnée, pour vous conformer à la condition 1 , vous devez avoir la connaissance de leurs valeurs numériques.

Donc, vous utilisez un mauvais outil. Regex ne peut pas vous aider ici. Ou même si vous obtenez une solution, ce sera trop complexe et trop difficile à développer.

La meilleure façon est de Split la chaîne sur virgule, puis comparez les nombres. p>

var numbers = input
       .Split(',') // split to an enumerable of strings
       .Select(int.Parse) // transform to an enumerable of numbers
       .ToArray(); // Creates an array from a IEnumerable<int>
return numbers.All(x => x > 0 && x <= 30) // range check
       && numbers.Length == numbers.Distinct().Length; // uniqueness check


0 commentaires

1
votes

il serait plus approprié d'utiliser Linq pour valider;

static bool IsValid(string input)
{
        var strings = input.Split(",");
        if (strings.Any(n => int.Parse(n) <= 0 || int.Parse(n) >= 31)) return false;      
        return new HashSet<string>(strings).Count == strings.Length;
}

ou mieux créer votre propre fonction personnalisée.

var isValid = input.Split(",")
                   .GroupBy(s => s)
                   .Select(g => new { Num = int.Parse(g.Key), Count = g.Count() })
                   .All(e => e.Count == 1 && e.Num > 0 && e.Num < 31);


0 commentaires

1
votes

Vous n'avez pas besoin de regex pour ce travail Vous pouvez essayer ceci

List<int> inputs = new List<int>();
//make sure the number in range
if(input > 0 && input < 31){
  //if there's another input would be added into list so make sure not equal the previous one
  if(inputs.count() > 0){
    if(input != inputs.Any()){
       inputs.Add(input);
     }
   }
 else{
  inputs.Add(input)
 }

Désolé, il n'a pas testé le code mais peut vous aider


0 commentaires

0
votes

Vous pouvez le faire sans expression régulière, mais comme réponse à votre question dans votre expression régulière, [1-3] [1-1] correspond à 11, 21 ou 31, donc vous correspondez à un motif répétitif de par exemple 31,1121,11.

Si vous voulez faire cela en utilisant une expression régulière, vous pouvez utiliser un modèle (?: [1-9] | [12] \ d | 30) code > pour correspondre à un nombre de 1 à 30, puis répétez ce modèle 0+ fois précédé d'une virgule.

Si ce format correspond, utilisez la division et vérifiez si le nombre d'éléments est égal à la version distincte.

Par exemple:

string pattern = @"^(?:[1-9]|[12]\d|30)(?:,(?:[1-9]|[12]\d|30))*$";
var input = "1,12,30";
List<String> a = input.Split(',').ToList();         
Console.WriteLine(Regex.Match(input, pattern).Success && a.Count == a.Distinct().Count()); // True

Voir la Démo C # | Démo Regex


0 commentaires