J'ai fait un commentaire hier sur une réponse où quelqu'un avait utilisé [0123456789]
une expression régulière plutôt que [0-9]
ou \d
. J'ai dit qu'il était probablement plus efficace d'utiliser un spécificateur de plage ou de chiffres qu'un jeu de caractères.
J'ai décidé de tester cela aujourd'hui et j'ai découvert à ma grande surprise que (dans le moteur C # regex au moins) \d
semble être moins efficace que les deux autres qui ne semblent pas différer beaucoup. Voici ma sortie de test sur 10000 chaînes aléatoires de 1000 caractères aléatoires dont 5077 contenant en fait un chiffre:
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
C'est une surprise pour moi pour deux raisons:
- J'aurais pensé que la gamme serait implémentée beaucoup plus efficacement que l'ensemble.
- Je ne comprends pas pourquoi
\d
est pire que[0-9]
. Y a-t-il plus\d
qu'un simple raccourci pour[0-9]
?
Voici le code de test:
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
la source
la source
\d
traite des paramètres régionaux. Par exemple, l'hébreu utilise des lettres pour les chiffres.\d
qu'elle ne signifie pas la même chose dans différentes langues. En Java, par exemple,\d
ne correspond en effet qu'à 0-9Réponses:
\d
vérifie tous les chiffres Unicode, tandis qu'il[0-9]
est limité à ces 10 caractères. Par exemple, les chiffres persans۱۲۳۴۵۶۷۸۹
, sont un exemple de chiffres Unicode qui correspondent\d
, mais pas[0-9]
.Vous pouvez générer une liste de tous ces caractères à l'aide du code suivant:
Ce qui génère:
la source
Nous remercions ByteBlast de l'avoir remarqué dans les documents. Il suffit de changer le constructeur d'expressions régulières:
Donne de nouveaux horaires:
la source
RegexOptions.ECMAScript
?ECMAScript
(\u1234
). Ce sont "juste" les classes de caractères sténographiques qui changent de sens (comme\d
) et les raccourcis de propriété / script Unicode qui disparaissent (comme\p{N}
).De «\ d» en regex signifie-t-il un chiffre? :
la source
If ECMAScript-compliant behavior is specified, \d is equivalent to [0-9].
var rex = new Regex(regex, RegexOptions.ECMAScript);
rend tous pratiquement indiscernables en termes de performances.En plus de la meilleure réponse de Sina Iravianian , voici une version .NET 4.5 (puisque seule cette version prend en charge la sortie UTF16, cf. les trois premières lignes) de son code, en utilisant la gamme complète de points de code Unicode. En raison du manque de prise en charge appropriée des avions Unicode supérieurs, de nombreuses personnes ne sont pas conscientes de toujours rechercher et inclure les avions Unicode supérieurs. Néanmoins, ils contiennent parfois des caractères importants.
Mise à jour
Étant donné
\d
que ne prend pas en charge les caractères non BMP dans l'expression régulière (merci xanatos ), voici une version qui utilise la base de données de caractères UnicodeDonnant la sortie suivante:
la source
Regex
ne prend pas en charge les caractères non BMP. Donc, à la fin, vérifier les caractères> 0xffff avec une expression régulière est inutile.\ d vérifie tous les Unicode, tandis que [0-9] est limité à ces 10 caractères. Si seulement 10 chiffres, vous devez utiliser. Autres, je recommande d'utiliser \ d , Parce que j'écris moins
la source