[英]How can I improve the speed of this LINQ query?
我正在使用long.TryParse
,但切换到正则表达式。 当前,一条123 + K消息总共需要7毫秒以上的时间。 从XElement.Parse到foreach方法的结尾是7毫秒以上。
Stopwatch s1 =Stopwatch.StartNew();
XElement element = XElement.Parse(xml);
string pattern = @"\b\d+\b";
Regex r = new Regex(pattern);
IEnumerable<XElement> elementsWithPossibleCCNumbers = element
.Descendants()
.Where(d => d.Attributes()
.Where(a => a.Value.Length >= 13 &&
a.Value.Length <= 16 &&
r.IsMatch(a.Value)).Count() == 1)
.Select(x => x);
foreach(var x in elementsWithPossibleCCNumbers)
{
foreach(var a in x.Attributes())
{
//Check if the value is a number
if(r.IsMatch(a.Value))
{
//Check if value is the credit card
if(a.Value.Length >= 13 && a.Value.Length <= 16)
{
a.Value = Regex.Replace(a.Value, @"\b\d{13,16}\b", match =>
new String('*', match.Value.Length - 4) +
match.Value.Substring(match.Value.Length - 4)
);
}
else //If value is not a credit card, replace it with ***
a.Value = Regex.Replace(a.Value ,@"\b\d+\b", "***");
}
}
}
xml = element.ToString();
s1.Stop();
XElement.Parse(xml);
耗时2-3毫秒。
LINQ查询需要0.004-0.005毫秒之间的时间。
foreach语句花费4到5毫秒之间。
看来您正在进行两次搜索和替换:
*
和最后4位数字 *
的。 一种方法是使XLinq对您来说更难一点:
// you're not using the elements, ignore them, just get the attributes
foreach (var atr in xelt.Descendants()
.Where(e => e.Attributes()
.Any(a => a.Value.Length >= 13
&& a.Value.Length <= 16))
.SelectMany(e => e.Attributes()))
{
// static basicDigits = new Regex(@"\b\d+\b", RegexOptions.Compiled);
// static ccDigits = new Regex(@"\b\d{13,16}\b", RegexOptions.Compiled);
if (ccDigits.IsMatch(atr.Value))
{
atr.Value = ccDigits.Replace(
atr.Value,
mm => new String('*', mm.Value.Length - 4)
+ mm.Value.Substring(mm.Value.Length - 4));
}
else
{
atr.Value = basicDigits.Replace(atr.Value, "***");
}
}
// using 150k XML (1k nodes/5k attrs, 3 attr/node avg, avg depth 4 nodes)
// with 10% match rate:
// - 25.7 MB/s (average 100 trials)
// - 61 attributes/ms
输入XML示例:
<item f1="abc123abc" f2="helloooo 1234567" f3="abc123abc">
<item f1="abc123abc" f2="helloooo 1234567" f3="abc123abc" real1="4444555566667777" />
<item f1="abc123abc" f2="helloooo 1234567" f3="abc123abc" />
ruBTMjSesurMsP6lK2jg
</item>
输出:
<item f1="abc123abc" f2="helloooo 1234567" f3="abc123abc">
<item f1="abc123abc" f2="helloooo ***" f3="abc123abc" real1="************7777" />
<item f1="abc123abc" f2="helloooo 1234567" f3="abc123abc" />
ruBTMjSesurMsP6lK2jg
</item>
您可能需要考虑预编译正则表达式。 此处的文章: http : //en.csharp-online.net/CSharp_Regular_Expression_Recipes%E2%80%94Compiling_Regular_Expressions很好地说明了编译正则表达式的优缺点。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.