【问题标题】:Filter with * which will restrain all values that starts with Null?使用 * 过滤将限制所有以 Null 开头的值?
【发布时间】:2015-06-21 07:22:55
【问题描述】:

我有以下代码,它扩展了我的过滤器功能,允许我搜索多个邮政编码。前任。 (1254,125,145,1455)

当前代码:

if (Post_Code_PAR != null)
{
    String[] PostCode_Array = Post_Code_PAR.Split(',');
    query = from p in query where PostCode_Array.Contains(p.Post_Code) select p;
}

我想以某种方式扩展此代码,如果我给它类似 (0*) 它会找到以 0 开头的邮政编码。如果我给它 123* 它会给我所有以 123 开头的邮政编码. 非常感谢。

【问题讨论】:

  • 您是否也希望能够对以123 结尾的事物执行*123 之类的操作,或者对以1 结尾和开头的事物执行1*1 之类的操作?
  • @Hjalmar:这也太好了,我能做到。

标签: c# filter filtering visual-studio-lightswitch


【解决方案1】:

使用正则表达式:

示例:

IEnumerable<string> allInputs = new[] {"70000", "89000", "89001", "90001"};
string commaSeparatedPostCodePatterns = @"89000 , 90\d\d\d";

if (string.IsNullOrWhiteSpace(commaSeparatedPostCodePatterns)) 
    return;

string[] postCodePatterns = commaSeparatedPostCodePatterns
                                .Split(',')
                                .Select(p => p.Trim()) // remove white spaces
                                .ToArray();

var allMatches = 
    allInputs.Where(input => postCodePatterns.Any(pattern => Regex.IsMatch(input, pattern)));

foreach (var match in allMatches)
    Console.WriteLine(match);

有了这样一个问题,最初的需求非常简单,但很快就变得越来越复杂(由于国际化,规则的例外,一些聪明的测试人员测试了一个意想不到的极限情况,比如90§$% ...)。所以正则表达式提供了最好的权衡简单性与可扩展性

* 等效的正则表达式是.*。但在您的情况下,您宁愿需要更多限制性模式并使用匹配单个数字的 \d 占位符。可选数字是\d?。零个或多个数字将是\d*。一位或多位数字是\d+。请查看文档以获取更多详细信息。

【讨论】:

  • 我刚刚使用Console.WriteLine() 来检查它在示例程序中是否有效:它将结果写入dos 控制台。您可以忽略最后两行。备注:确实更喜欢 linq 语法 myList.Where(...) 而不是 from myItem in myList ...:在大多数情况下,它更具可读性。
  • 查看响应的补充
  • 如果您想在您的邮政编码模式中保留单个* ,您可以在开头使用myString.Replace("*", ".*") 即时替换它。这样,您就可以为将来的扩展保留正则表达式的强大功能,并继续避免使用 if 语句。
  • 您可以将示例代码复制并粘贴到 C# 控制台应用程序的public static void Main() 入口点,它会编译并运行。从这一点开始,您可以根据需要对其进行调整并测试结果。
  • 备注:我根本不是正则表达式专家。几年前我刚刚学会使用它们来满足类似的需求。我发现最好的学习方法是使用 regexbuddy 软件。但你也可以在 stackoverflow 上提问,也许在一个单独的问题中。
【解决方案2】:

基本上,您可以将* 替换为\d*,这是表示“任意数量的数字”的正则表达式。然后使用Regex.IsMatch() 运行并过滤。

if (Post_Code_PAR != null)
{
    var PostCode_Array = from p in Post_Code_PAR.Split(',') select String.Format("^{0}$", p.Replace("*", @"\d*"));
    query = (from p in query where PostCode_Array.Any(pattern => Regex.IsMatch(p.Post_Code, pattern)) select p).ToArray();
}

我试图让它尽可能接近您的代码,但您可以稍微清理一下并改用 lambda。但这应该也可以:)

【讨论】:

  • 在文档顶部添加using System.Text.RegularExpressions;
  • 它在哪里说的?
  • 仅供参考:我的数据集中的字段邮政编码是一个字符串,参数也是一个字符串
  • 我好像忘记获取属性了,再试一次
  • 您好,现在我在您的“选择”下有一条红线,出现此错误“错误 9 类型 'System.Collections.Generic.IEnumerable ”无法隐式转换为'字符串 [] '。已经存在显式转换。 (也许你错过了一个演员。)“
【解决方案3】:
string Post_Code_PAR = "";
String[] PostCode_Array = Post_Code_PAR.Split(',');
var zipCodeList = query.Where(x => CustomFilter(x.Post_Code, PostCode_Array)).ToList();

private static bool CustomFilter(string code, string[] foundZipCodes)
{
    return foundZipCodes.Any(x =>
   {
       x = x.Trim();
       var text = x.Replace("*", "");
       if (x.EndsWith("*"))
           return code.StartsWith(text);
       if (x.StartsWith("*"))
           return code.EndsWith(text);
       if (x.Contains("*"))
           return false;
       return code.StartsWith(text);
    });

}

现在用户可以找到:“0*,*52”等

【讨论】:

  • 嗨 Bondaryuk:这行“query = from p in query where PostCode_Array.Contains(p.Post_Code) select p;”怎么样?我应该删除它吗?
  • @Zayed 是的,你可以。如果你只想开始使用 var zipCodeList = PostCode_Array.Where(x => x.StartsWith(startWith));
  • 嗨,我不明白你在做什么这个 var filter = "0";?.我有一个名为“Post_Code_PAR”的参数,用户在其中输入值。我想过滤那些 vales,以防他写了 1455 之类的东西 --> 这将得到所有以 1455 开头的 vales
  • @Zayed 抱歉,我理解你,现在我改变答案,现在用户可以找到:“231, 254”它返回 StartsWith 和 EndWith
  • 你的意思是如果我输入 123* 我会得到所有以 123 开头的数字?因为这就是我想要的
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2022-01-06
  • 2015-06-20
  • 2017-07-15
  • 1970-01-01
相关资源
最近更新 更多