C#Linq从结果中删除字符以进行比较

问题描述

我有一个linq查询,该查询sql Server数据库获取记录。例如,电话号码存储为字符串,并且可以包含在搜索时找不到的空格或字符。

即我搜索电话号码“ 0123456789”,但在数据库中将其存储为“ 01234 567890”或“ 01234-567890”等。在下面的代码中,您可以看到我试图去除字符(对还是错!)的尝试,但是我除非我在空格“ 567890”之后搜索字符,否则仍然不会获得任何结果。

使用以下代码

“ 567890”返回正确的结果

“ 01202 567890”没有返回结果

“ 01202567890”未返回任何结果

    Expression<Func<Customer,bool>> SearchVals = ContainsInDescription("01234567890");

    var query = (from customer in data.Customers.Where(SearchVals)
                                 where customer.Deleted == false
                                 orderby customer.Name ascending
                                 select new
                                 {
                                     CustomerID = customer.CustomerID.ToString(),Name = customer.Name,Company = customer.Company,Home = customer.PhoneHome.Replace(" ",""),Mobile = customer.PhoneMobile.Replace(" ",Work = customer.PhoneWork.Replace(" ",Email = customer.Email,Address1 = customer.Address.AddressLine1,Address2 = customer.Address.AddressLine2,City = customer.Address.City,County = customer.Address.County,Postcode = customer.Address.PostalCode,Country = customer.Address.Country
                                 }).Skip(totalTodisplay * page).Take(totalTodisplay);

public Expression<Func<Customer,bool>> ContainsInDescription(
                                                        params string[] keywords)
        {
            Expression<Func<Customer,bool>> predicate = PredicateBuilder.False<Customer>();
            foreach (string keyword in keywords)
            {
                string temp = keyword;

                //string predicate1 = PhoneHome.ToString().Replace(" ","").Replace("-","").Replace("(","").Replace(")","").Trim();
                string predicate2 = temp.ToString().Replace(" ","").Trim();

                predicate = predicate.Or(p => p.Name.Contains(temp));
                predicate = predicate.Or(p => p.Company.Contains(temp));

                predicate = predicate.Or(p => p.PhoneHome.Contains(temp));
                predicate = predicate.Or(p => p.PhoneMobile.Contains(temp));
                predicate = predicate.Or(p => p.PhoneWork.Contains(temp));
                //predicate = predicate.Or(p => p.PhoneHome.ToString().Replace(" ","").Contains(temp.ToString().Replace(" ","")));
                //predicate = predicate.Or(p => p.PhoneMobile.ToString().Replace(" ","")));
                //predicate = predicate.Or(p => p.PhoneWork.ToString().Replace(" ","")));
                //predicate = predicate.Or(p => p.PhoneHome.ToString().Replace(" ","").Trim() == temp.ToString().Replace(" ","").Trim());
                //predicate = predicate.Or(p => p.PhoneMobile.ToString().Replace(" ","").Trim());
                //predicate = predicate.Or(p => p.PhoneWork.ToString().Replace(" ","").Trim());

                predicate = predicate.Or(p => p.Email.Contains(temp));
                predicate = predicate.Or(p => p.Address.AddressLine1.Contains(temp));
                predicate = predicate.Or(p => p.Address.AddressLine2.Contains(temp));
                predicate = predicate.Or(p => p.Address.City.Contains(temp));
                predicate = predicate.Or(p => p.Address.County.Contains(temp));
                predicate = predicate.Or(p => p.Address.PostalCode.Contains(temp));
                predicate = predicate.Or(p => p.Address.Country.Contains(temp));
            }
            return predicate;
        }

解决方法

您可能还需要清除从数据库收集的数据。当前,您仅删除空格。与其使用大量白名单方法,不如替换很多东西:

using System;
using System.Linq;
using System.Text;

public static void Main()
{
    Func<string,String> onlyNumbers = data 
      => data.Where(c => char.IsDigit(c))  // only keep digits
             .Aggregate(new StringBuilder(),(builder,c) => builder.Append(c))
             .ToString(); // gimme concatted string
    
    Console.WriteLine(onlyNumbers( "sadf(234)-23492sas" ));  // =>   "23423492"
}

在“更清洁”上方使用类似

...
Mobile = onlyNumbers(customer.PhoneMobile),Home = onlyNumbers(customer.PhoneHome),Mobile = onlyNumbers(customer.PhoneMobile),Work = onlyNumbers(customer.PhoneWork),...

pred = pred.Or(p => p.Mobile.Contains(onlyNumbers(_some_input_)));

应该可以解决问题。

您可以定义自己的允许字符(或也允许'+')的哈希集,而不是char.IsDigit()来允许f国际预拨号码为+41 1234 5678 90

注意-这会从任何文本中产生数字,可能会给您带来假阳性:

onlyNumbers("This 246 cars had 102 violations of rule 47.11 in the year 2012");

为您提供一串"24610247112012"