Replaceи
Splitимеют минимальные простые обертки, к низкоуровневым реализациям. наверняка аналоги давно есть в рантаймах типа user32.dll, или где то рядом ))
В итоге побеждает Replace - изящное и, на мой взгляд, далеко не очевидное решение.тоже интересный прием..
смогу написать только ближе к понедельникуне вопрос, даже если и не сложится. но если сложится - мне проще заходить на "новые территории" сравнивая решения задачи, которая уже решена знакомым способом. как наверное и всем ))
если будут вопросы по F# с радостью отвечу, если смогу, конечно.а переписать на F# мой "бенчмарк".. хлопотно? было бы любопытно ))
static int useIndex(this string source, string pattern)
{
for (int count = 0, index = 0; ; count++)
if ((index = source.IndexOf(pattern, index)) < 0)
return count;
else
index += pattern.Length;
}
ухожу, ухожу, ухожу ... (с)
static int useIndex(this string source, string pattern)
{
var count = 0;
var index = 0;
while (true)
if ((index = source.IndexOf(pattern, index)) < 0)
return count;
else
{
index += pattern.Length;
count++;
}
}
static int useIndex(this string source, string pattern)
{
var count = 0;
var index = 0;
while (true)
{
index = source.IndexOf(pattern, index);
if (index < 0)
return count;
index += pattern.Length;
count++;
}
}
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Text;
using System.Text.RegularExpressions;
namespace Occurrences
{
static class Program
{
static int useSubString(this string source, string pattern)
{
var count = 0;
while (true)
{
var index = source.IndexOf(pattern);
if (index < 0)
return count;
source = source.Substring(index + pattern.Length);
count++;
}
}
static int useRemove(this string source, string pattern)
{
var count = 0;
while (true)
{
var index = source.IndexOf(pattern);
if (index < 0)
return count;
source = source.Remove(index, pattern.Length);
count++;
}
}
static int useIndex(this string source, string pattern)
{
var count = 0;
var pos = 0;
var len = pattern.Length;
while (true)
{
var index = source.IndexOf(pattern, pos);
if (index < 0)
return count;
pos = index + len;
count++;
}
}
static int useSplit(this string source, string pattern)
=> source.Split(new string[] { pattern }, StringSplitOptions.None).Count() - 1;
static int useRegexp(this string source, string pattern)
=> new Regex(pattern).Matches(source).Count;
static void sample(string src = "тук - тук!", string ptn = "тук")
{
$"'{ptn}' found on '{src}' use 'useSubString'\t {src.useSubString(ptn)} times...".print();
$"'{ptn}' found on '{src}' use 'useRemove'\t {src.useRemove(ptn)} times...".print();
$"'{ptn}' found on '{src}' use 'useIndexOf'\t {src.useIndex(ptn)} times...".print();
$"'{ptn}' found on '{src}' use 'useSplit'\t {src.useSplit(ptn)} times...".print();
$"'{ptn}' found on '{src}' use 'useRegexp'\t {src.useRegexp(ptn)} times...".print();
}
static Random rnd = new Random();
static string pattren = genPattern();
static string genPattern()
{
var l = rnd.Next(10, 20);
var sb = new StringBuilder();
for (var i = 0; i < l; i++)
sb.Append((char)('A' + (char)rnd.Next(0, 26)));
return sb.ToString();
}
static List<string> sources = new List<string>();
static void fill(int n)
{
for (var i = 0; i < n; i++)
{
var l = rnd.Next(10, 20);
var sb = new StringBuilder();
for (var j = 0; j < l; j++)
if (rnd.Next(0, 7) % 3 != 0)
sb.Append((char)('A' + (char)rnd.Next(0, 26)));
else
sb.Append(pattren);
sources.Add(sb.ToString());
}
}
static void bench(int n = 1_000_000, bool check = true)
{
// массивы что бы убрать влияние динамического создания объектов
var uss = new int[n];
var urm = new int[n];
var uio = new int[n];
var usp = new int[n];
var urx = new int[n];
var sw = new Stopwatch();
sw.Start();
fill(n);
var tsf = sw.Elapsed;
sw.Reset();
sw.Start();
for (var i = 0; i < n; i++)
uss[i] = sources[i].useSubString(pattren);
var tss = sw.Elapsed;
sw.Reset();
sw.Start();
for (var i = 0; i < n; i++)
urm[i] = sources[i].useRemove(pattren);
var trm = sw.Elapsed;
sw.Reset();
sw.Start();
for (var i = 0; i < n; i++)
uio[i] = sources[i].useIndex(pattren);
var tio = sw.Elapsed;
sw.Reset();
sw.Start();
for (var i = 0; i < n; i++)
usp[i] = sources[i].useSplit(pattren);
var tsp = sw.Elapsed;
sw.Reset();
sw.Start();
for (var i = 0; i < n; i++)
urx[i] = sources[i].useRegexp(pattren);
var trx = sw.Elapsed;
sw.Stop();
// весь вывод выносим за пределы замера
$"fill\t\t {tsf.ToString(@"hh\:mm\:ss\.fffff")}".print();
$"useSubString\t {tss.ToString(@"hh\:mm\:ss\.fffff")}".print();
$"useRemove\t {trm.ToString(@"hh\:mm\:ss\.fffff")}".print();
$"useIndexOf\t {tio.ToString(@"hh\:mm\:ss\.fffff")}".print();
$"useSplit\t {tsp.ToString(@"hh\:mm\:ss\.fffff")}".print();
$"useRegexp\t {trx.ToString(@"hh\:mm\:ss\.fffff")}".print();
// выод размерности массивов, или чек, что бы сборщик мусора не успел возбудиться ))
if (check)
$"{chk(urm)} {chk(usp)} {chk(uio)} {chk(urx)}".print();
else
$"{uss.Length} {urm.Length} {usp.Length} {urx.Length}".print();
bool chk(int[] x)
{
for (var i = 0; i < x.Length; i++)
if (uss[i] != x[i])
return false;
return true;
}
}
static void Main(string[] args)
{
sample();
bench();
}
static void print(this string s) => Console.WriteLine(s);
}
}
.. это взаимная мотивация.. и она того стоит )) .. успехов