【问题标题】:How to check if a string contains chars that are outside of a given char list如何检查字符串是否包含给定字符列表之外的字符
【发布时间】:2018-12-18 19:57:29
【问题描述】:

我有一个字符串,我需要检查这个字符串是否包含任何不在给定列表中的字符。

假设我有这个允许的字符new char[] { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9' , '.'}

如果字符串是“54323.5” - 这没关系!

如果字符串是“543g23.5” - 这不行,因为它包含不在我允许的字符列表中的“g”。

空字符串被认为是无效的。

我试图通过使用“IndexOfAny()”来实现这一点,但到目前为止还没有运气。当然,将所有不允许的字符传递给此方法不是解决方案。

请注意,允许的字符列表可能会更改,并且根据列表更改更改验证算法不被视为解决方案。

对于那些问我尝试过的代码的人,这里是:

        private bool CheckInvalidInput(string stringToCheck)
    {
        char[] allowedChars = new char[] { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9' };

        var chars = Enumerable.Range(0, char.MaxValue + 1)
                  .Select(i => (char)i)
                  .ToArray();

        var unallowedChars = chars.Except(allowedChars).ToArray();

        bool validString = true;
        if(stringToCheck.IndexOfAny(unallowedChars) != -1)
        {
            validString = false;
        }

        return validString;
    }

希望您能提供更好的解决方案:D。

【问题讨论】:

  • 请提供您尝试过的代码
  • 使用 Enumerable 扩展方法 (System.Linq):AnyContains 如果使用得当,就可以完成这项工作。
  • @Greg 我发布了我尝试过的代码,你能做得更好吗?以及为此投票的其他人。不知道为什么有人对这个问题投了反对票。
  • 就这么做 - foreach (char in testString) 和内部 foreach (char in allowed chars)。如果您需要性能 - 首先制作 64k 的 bool 数组,以 chars 作为索引,然后 foreach (char in testString) 并检查该数组的余量 - 您将拥有 O(N)
  • @Lanorkin 你的建议听起来很不错我会这样尝试,并且使用下面建议的正则表达式方法,使用更少代码的解决方案将获胜:)。

标签: c# .net regex


【解决方案1】:

这很容易实现。 string 类型实现了IEnumerable<char>,因此您可以使用 LINQ All 方法检查其所有字符是否满足谓词。在您的情况下,谓词是每个字符都包含在allowedChars 集中,因此您可以使用Contains 方法:

private static bool CheckInvalidInput(string stringToCheck, IEnumerable<char> allowedChars)
{
    return stringToCheck.All(allowedChars.Contains);
}

如果您的 allowedChars 集变大,您可能需要将其转换为 HashSet&lt;char&gt; 以获得更好的性能。

完整示例:

using System;
using System.Linq;
using System.Collections.Generic;

public class Test
{
    public static void Main()
    {
        // var allowedChars = new char[] { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '.' };
        var allowedChars = "0123456789.";

        Console.WriteLine(CheckInvalidInput("54323.5", allowedChars));   // True
        Console.WriteLine(CheckInvalidInput("543g23.5", allowedChars));  // False
    }

    private static bool CheckInvalidInput(string stringToCheck, IEnumerable<char> allowedChars)
    {
        return stringToCheck.All(allowedChars.Contains);
    }
}

【讨论】:

    【解决方案2】:

    这可以使用非常简单的模式来完成。 Regex.IsMatch(yourString, @"^[\d.]+$");

    ^ 是行首

    [\d.]+ 匹配一个或多个字符(.0-9

    $ 是行尾

    Demo

    编辑:这也将匹配.

    如果此行为不是有意的,请尝试使用此^(?=\d)[\d.]+$

    【讨论】:

    • 嗨,是的,这对于我在示例中给出的字符集可以正常工作,但是允许的字符列表可能会发生变化,因此它包含数字和其他一些字符,例如“- " 、 "/" 等。
    • 因此,如果您需要添加任何其他可接受的字符,只需将它们放在方括号之间,如下所示:[\d.\-/]
    • 您的建议肯定会奏效,但每次更改“允许”字符列表时,我都必须更改正则表达式,这是“额外”的东西。我只想更改“允许”字符的列表,并使用相同的规则表达式或验证算法来检查我的输入是否正常。
    • 因此,将原始正则表达式模式保存为字符串,然后当您知道需要包含哪些符号时,使用 pattern.Insert(pattern.IndexOf("[" + 1), symbolsToAdd); 将它们添加到字符串中,其中 symbolsToAdd 类似于 "$%^& "
    • 你用正则表达式标记了这个问题,但使用字符数组不是正则表达式解决方案
    【解决方案3】:

    如果允许的字符数组是动态的,您可以创建过程来接受允许的字符数组并动态构建模式。请注意,您必须转义某些字符才能在 Regex 中使用:

    static void TestRegex(char[] check_chars)
    {
        string[] inputs = { "54323.5", "543g23.5" };
        var check_chars2 = check_chars.Select(c => Regex.Escape(c.ToString()));
        string pattern = "^(" + string.Join("|", check_chars2) + ")+$";
        foreach (string input in inputs)
        {
            WriteLine($"Input {input} does{(Regex.IsMatch(input, pattern) ? "" : " not")} match");
        }
    }
    
    // Output:
    // Input 54323.5 does match
    // Input 543g23.5 does not match
    

    【讨论】:

      猜你喜欢
      • 2013-01-01
      • 1970-01-01
      • 2018-06-14
      • 2017-09-23
      • 2014-01-08
      • 1970-01-01
      • 1970-01-01
      • 2020-02-26
      • 1970-01-01
      相关资源
      最近更新 更多