Tôi đã đưa ra một nhận xét ngày hôm qua về một câu trả lời mà ai đó đã sử dụng [0123456789]
trong một biểu thức thông thường hơn là [0-9]
hoặc \d
. Tôi đã nói rằng có thể hiệu quả hơn khi sử dụng một công cụ xác định phạm vi hoặc chữ số so với một bộ ký tự.
Tôi đã quyết định kiểm tra điều đó hôm nay và phát hiện ra điều ngạc nhiên là (ít nhất là trong công cụ regex C #) có \d
vẻ kém hiệu quả hơn so với hai trong số hai cái còn lại dường như không khác nhau nhiều. Đây là đầu ra thử nghiệm của tôi hơn 10000 chuỗi ngẫu nhiên gồm 1000 ký tự ngẫu nhiên với 5077 thực sự có chứa một chữ số:
Regular expression \d took 00:00:00.2141226 result: 5077/10000
Regular expression [0-9] took 00:00:00.1357972 result: 5077/10000 63.42 % of first
Regular expression [0123456789] took 00:00:00.1388997 result: 5077/10000 64.87 % of first
Đó là một bất ngờ đối với tôi vì hai lý do:
- Tôi đã nghĩ rằng phạm vi sẽ được thực hiện hiệu quả hơn nhiều so với thiết lập.
- Tôi không thể hiểu tại sao
\d
tồi tệ hơn[0-9]
. Có nhiều\d
hơn chỉ đơn giản là tốc ký cho[0-9]
?
Đây là mã kiểm tra:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Diagnostics;
using System.Text.RegularExpressions;
namespace SO_RegexPerformance
{
class Program
{
static void Main(string[] args)
{
var rand = new Random(1234);
var strings = new List<string>();
//10K random strings
for (var i = 0; i < 10000; i++)
{
//Generate random string
var sb = new StringBuilder();
for (var c = 0; c < 1000; c++)
{
//Add a-z randomly
sb.Append((char)('a' + rand.Next(26)));
}
//In roughly 50% of them, put a digit
if (rand.Next(2) == 0)
{
//Replace one character with a digit, 0-9
sb[rand.Next(sb.Length)] = (char)('0' + rand.Next(10));
}
strings.Add(sb.ToString());
}
var baseTime = testPerfomance(strings, @"\d");
Console.WriteLine();
var testTime = testPerfomance(strings, "[0-9]");
Console.WriteLine(" {0:P2} of first", testTime.TotalMilliseconds / baseTime.TotalMilliseconds);
testTime = testPerfomance(strings, "[0123456789]");
Console.WriteLine(" {0:P2} of first", testTime.TotalMilliseconds / baseTime.TotalMilliseconds);
}
private static TimeSpan testPerfomance(List<string> strings, string regex)
{
var sw = new Stopwatch();
int successes = 0;
var rex = new Regex(regex);
sw.Start();
foreach (var str in strings)
{
if (rex.Match(str).Success)
{
successes++;
}
}
sw.Stop();
Console.Write("Regex {0,-12} took {1} result: {2}/{3}", regex, sw.Elapsed, successes, strings.Count);
return sw.Elapsed;
}
}
}
\d
không có nghĩa giống nhau trong các ngôn ngữ khác nhau. Trong Java, ví dụ \d
, thực sự chỉ khớp 0-9
\d
giao dịch với các địa phương. Ví dụ: tiếng Do Thái sử dụng các chữ cái cho các chữ số.