【问题标题】:match if string list has specific string c# tried .Any如果字符串列表具有特定字符串,则匹配 c# 尝试过 .Any
【发布时间】:2020-05-22 07:14:30
【问题描述】:

我必须为密码列添加验证器,即它不应在任何阶段在密码中允许“密码”字样..意味着不应允许“密码@1234”。所以我使用了下面的代码,它工作正常:

Regex.IsMatch(viewModel.Password.ToUpper(), @"(\w*PASSWORD\w*)", RegexOptions.IgnoreCase)

现在我想比较多个单词意味着它不应该包含“密码”或“你好”让我们说。我试过“.Any”,但它不起作用。

if (myList.Any(str => str.Contains("Password")))

我已关注:

Check if a string within a list contains a specific string with Linq

适用于任何

请帮忙。

【问题讨论】:

  • 多个“单词”是什么意思?你的意思是一个句子仍然存储为一个字符串,比如“这有很多词”,还是你的意思是一个词的集合,比如List<string> {"this", "is", "a", "collection", "of", "words"}
  • 列表 {"this", "is", "a", "collection", "of", "words"}
  • 那么您到底尝试了什么?你说过你试过Any()..这段代码是什么样的?
  • 那是因为你改变了你正在检查的内容......你的第一个例子是对密码的大写版本进行正则表达式检查。你的Any 版本只是做一个基本的包含

标签: c# string list linq


【解决方案1】:

是的,你可以试试 Linq Any单词定义是一个复杂的问题,所以让我坚持你的模式: \w*{word_to_find}\w*):

  List<string> ForbiddenWords = new List<string>() {
    "this",
    "password",
    "bla-bla-bla",
    "123",
  };

  Regex[] invalidPasswords = ForbiddenWords
    .Select(word => new Regex($@"\w*{Regex.Escape(word)}\w*", RegexOptions.IgnoreCase))
    .ToArray();

  ...

  if (invalidPasswords.Any(regex => regex.IsMatch(viewModel.Password))) {
    // Password is invalid it contains forbidden word(s)
  } 

让我们做一些演示:

  string[] tests = new string[] {
    "MyPassWord",
    "PassWord",
    "PassWord@123",
    "PassWord@5678",
    "It's_PassWord@5678",
    "ABC123",
    "123",
    "1234",
    "pass",
    "word",
    "swar",
  };

  Func<string, bool> Validator = (password) => 
    !invalidPaswords.Any(regex => regex.IsMatch(password));

  string report = string.Join(Environment.NewLine, tests
    .Select(test => $"{test,-20} : {(Validator(test) ? "OK" : "Invalid")}"));

  Console.Write(report);

结果:

MyPassWord           : Invalid
PassWord             : Invalid
PassWord@123         : Invalid
PassWord@5678        : Invalid
It's_PassWord@5678   : Invalid
ABC123               : Invalid
123                  : Invalid
1234                 : Invalid
pass                 : OK
word                 : OK
swar                 : OK

【讨论】:

  • @Ram Singh:Password@1234无效:它包含password123 禁用词;
  • 不,因为 \w* 表示:a-z、A-Z、0-9 和下划线。如果添加特殊字符,它将不起作用,并且 regex.IsMatch 将返回 false。
  • @DmitryBychenko 它不会无效。您的正则表达式只需要单词(和禁止的单词)。它永远不会匹配。不要为此使用正则表达式。
  • @Lucca Ferri:单词定义是一个复杂的问题(是字母序列还是数字序列,\s、@ 987654330@ 等),这就是我刚刚从问题中提取模式的原因
【解决方案2】:

您可以尝试以下方法,

通过正则表达式

bool res = Regex.IsMatch(viewModel.Password.ToUpper(), @"(\w*PASSWORD\w*)|(\w*HELLO\w*)", RegexOptions.IgnoreCase);

通过 LINQ

var forbiddenWords = new List<string>() { "PASSWORD", "HELLO" };
bool res = forbiddenWords.Any(x => viewModel.Password.ToUpper().Contains(x));

【讨论】:

    【解决方案3】:

    也许您的 .Any 是错误的。你试过吗?

        static bool ContainsBlacklistedWords(string password, string[] blacklist)
        {
            return blacklist.Any(s => password.Contains(s, StringComparison.CurrentCultureIgnoreCase));
        }
        static void Main(string[] args)
        {
            string password = "foobar";
            string[] blacklist = new[] { "hello", "password" };
    
            if (ContainsBlacklistedWords(password, blacklist))
            {
                Console.WriteLine("Contains blocked words.");
            }
            else
            {
                Console.WriteLine("OK");
            }
         }
    

    工作得很好。不需要正则表达式。


    这是错误的:

    if (myList.Any(str => str.Contains("Password")))
    

    这将类似于(仅用于解释的示例):

    foreach (var str in myList)
    {
          if (str.Contains("Password"))
          {
                  return true;
          }
    }
    return false;
    

    那么,在上面的这段代码中(逻辑上与 Any() 相同),你在哪里输入密码?您正在循环搜索“密码”的列表,而不是根据列表检查密码。

    如果你使用我上面展示的方法,它应该会按照你喜欢的方式工作。我不会正则表达式,特别是如果您的列表很大。

    【讨论】:

      猜你喜欢
      • 2018-06-12
      • 1970-01-01
      • 2014-10-08
      • 1970-01-01
      • 2015-12-02
      • 1970-01-01
      • 2021-03-05
      • 2020-10-01
      • 1970-01-01
      相关资源
      最近更新 更多