Saya membuat komentar kemarin pada jawaban di mana seseorang telah digunakan [0123456789]
dalam ekspresi reguler daripada [0-9]
atau \d
. Saya mengatakan mungkin lebih efisien menggunakan rentang atau digit specifier daripada set karakter.
Saya memutuskan untuk mengujinya hari ini dan mengejutkan saya bahwa (di mesin C # regex setidaknya) \d
tampaknya kurang efisien daripada salah satu dari dua lainnya yang tampaknya tidak jauh berbeda. Berikut ini adalah hasil pengujian saya lebih dari 10.000 string acak 1000 karakter acak dengan 5077 sebenarnya mengandung digit:
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
Ini mengejutkan saya karena dua alasan:
- Saya akan berpikir jangkauan akan diimplementasikan jauh lebih efisien daripada yang ditetapkan.
- Saya tidak mengerti mengapa
\d
lebih buruk dari itu[0-9]
. Apakah ada lebih\d
dari sekadar singkatan[0-9]
?
Ini adalah kode tes:
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;
}
}
}
c#
regex
performance
Weston
sumber
sumber
\d
berurusan dengan lokal. Misalnya bahasa Ibrani menggunakan huruf untuk angka.\d
tidak berarti hal yang sama dalam berbagai bahasa. Di Jawa, misalnya\d
memang hanya cocok dengan 0-9Jawaban:
\d
memeriksa semua digit Unicode, sementara[0-9]
terbatas pada 10 karakter ini. Misalnya, digit Persia۱۲۳۴۵۶۷۸۹
,, adalah contoh digit Unicode yang cocok dengan\d
, tetapi tidak[0-9]
.Anda dapat membuat daftar semua karakter tersebut menggunakan kode berikut:
Yang menghasilkan:
sumber
Penghargaan untuk ByteBlast karena memperhatikan hal ini dalam dokumen. Hanya mengubah konstruktor regex:
Memberikan timing baru:
sumber
RegexOptions.ECMAScript
dilakukan?ECMAScript
(\u1234
). "Hanya" kelas karakter steno yang mengubah makna (seperti\d
) dan steno properti / skrip Unicode yang hilang (seperti\p{N}
).Dari Apakah “\ d” dalam regex berarti digit? :
sumber
If ECMAScript-compliant behavior is specified, \d is equivalent to [0-9].
var rex = new Regex(regex, RegexOptions.ECMAScript);
membuat semuanya tidak bisa dibedakan dari segi kinerja.Tambahan untuk jawaban teratas dari Sina Iravianian , di sini adalah versi .NET 4.5 (karena hanya versi yang mendukung output UTF16, cf tiga baris pertama) dari kodenya, menggunakan berbagai titik kode Unicode. Karena kurangnya dukungan yang tepat untuk pesawat Unicode yang lebih tinggi, banyak orang tidak menyadari selalu memeriksa dan termasuk pesawat Unicode atas. Meskipun demikian mereka terkadang mengandung beberapa karakter penting.
Memperbarui
Karena
\d
tidak mendukung karakter non-BMP di regex (terima kasih xanatos ), di sini versi yang menggunakan basis data karakter UnicodeMenghasilkan output berikut:
sumber
Regex
tidak mendukung karakter non-BMP. Jadi pada akhirnya memeriksa karakter> 0xffff dengan regex tidak berguna.Memeriksa semua Unicode, sementara [0-9] terbatas pada 10 karakter ini. Jika hanya 10 digit, Anda harus menggunakan. Yang lainnya saya sarankan menggunakan \ d , Karena menulis lebih sedikit.
sumber