正確なデータの分布にもよりますが、各検索でループする可能性は非常に低いです。あなたは間違いなく非常に大きな文字列を何度も繰り返して行きたくはありません。簡単なベンチマークを作ることができます。
string lorem = @"Lorem ipsum dolor ,Fizz! amet, consectetur
adipiscing elit. Nulla
laoreet .Fizz! facilisis. Mauris :Buzz! efficitur nisi. Morbi
consectetur hendrerit pretium. Ut tempor mauris ,Buzz! consequat
convallis. Quisque lacinia felis in ex lacinia, luctus malesuada
purus tristique. Nullam tincidunt dolor sit amet metus vehicula, Foo
amet fringilla lacus ultrices. Maecenas semper .Fizz! le justo molestie,
non ultrices Buzz! consequat. Donec :Foo? facilisis tellus. Nunc
pulvinar egestas turpis. Donec sed ex rhoncus, Fizz dolor eget,
aliquam orci..Foo! tincidunt pellentesque dolor sed mollis.";
StringBuilder sb = new StringBuilder();
for (int i = 0; i < 10000; ++i)
{
sb.Append(lorem);
}
int lensb = sb.Length;
Random rnd = new Random(1);
for (int i = 0; i < 100000; ++i)
{
sb[rnd.Next(lensb)] = '!';
sb[rnd.Next(lensb)] = '?';
sb[rnd.Next(lensb)] = '.';
sb[rnd.Next(lensb)] = ',';
sb[rnd.Next(lensb)] = ':';
sb[rnd.Next(lensb)] = lorem[rnd.Next(lorem.Length)];
}
string sample = sb.ToString();
をし、テスト
Regex r = new Regex("[,.:](Fizz|Buzz|Foo|Bar|eeeeeeeeeo|kjkjsh|iousadh|kjlsadh|jfsfs|sdfs)[?!]", RegexOptions.Compiled);
HashSet<string> matches = new HashSet<string>();
foreach (Match match in r.Matches(sample))
{
matches.Add(match.Groups[1].Value);
}//240ms
悪くない操作を行います。いくつかのダミーデータを作成します。そして今、ループ:
List<string> matches = new List<string>();
foreach (string s in new string[] { "Fizz", "Buzz", "Foo", "Bar", "eeeeeeeeeo", "kjkjsh", "iousadh", "kjlsadh", "jfsfs", "sdfs" })
{
if (Regex.IsMatch(sample, "[,.:]" + s + "[?!]", RegexOptions.Compiled))
{
matches.Add(s);
}
}//890ms
期待通り、遅いです。しかし、正規表現はおそらくここで最高の演奏者オプションではありません。パフォーマンスが本当に必要な場合は、
enum State { NA, DOT, STR };
HashSet<string> ok = new HashSet<string>() { "Fizz", "Buzz", "Foo", "Bar", "eeeeeeeeeo", "kjkjsh", "iousadh", "kjlsadh", "jfsfs", "sdfs" };
List<string> matches = new List<string>();
int len = sample.Length;
int start = -1;
State state = State.NA;
for (int i = 0; i < len; ++i)
{
char c = sample[i];
switch (state)
{
case State.NA:
if (c == '.' || c == ',' || c == ':')
{
start = i;
state = State.DOT;
}
break;
case State.DOT:
if (c == '.' || c == ',' || c == ':')
{
start = i;
continue;
}
if (c == '!' || c == '?')
{
state = State.NA;
continue;
}
state = State.STR;
break;
case State.STR:
if (c == '.' || c == ',' || c == ':')
{
start = i;
state = State.DOT;
continue;
}
if (c == '!' || c == '?')
{
state = State.NA;
string substr = sample.Substring(start + 1, i - start - 1);
if (ok.Contains(substr))
{
matches.Add(substr);
ok.Remove(substr);
}
continue;
}
break;
}
}//30ms
のようになるでしょう。あなたは既にFizz、Buzz、Foo、またはBarの組み合わせが最初からあることを知っています。 [、。:]と[?!]の間にはっきりとしたマッチをすべて見つけなければなりませんか? – juharr
私はFizz、Buzz、Foo、またはBarを探しているのを知っていますが、私がそれらのどれかを見つけるかどうかはわかりません。私はちょうど存在するものを知りたい。自分の位置や頻度、実際の接頭辞/接尾辞の一致を知る必要はありません。 – ThunderFrame
ええ、IsMatchは可能な一致が少なくても私が行くオプションです。 – juharr