我正在做一些事情,我意识到我想要计算/
我能在字符串中找到多少,然后它让我感到震惊,有几种方法可以做到,但无法决定最好的(或最简单的)是什么.
目前我正在做的事情如下:
string source = "/once/upon/a/time/"; int count = source.Length - source.Replace("/", "").Length;
但我完全不喜欢它,任何接受者?
我真的不想挖掘RegEx
这个,是吗?
我知道我的字符串将会有我正在搜索的术语,所以你可以认为......
当然,对于字符串,其中 长度> 1,
string haystack = "/once/upon/a/time"; string needle = "/"; int needleCount = ( haystack.Length - haystack.Replace(needle,"").Length ) / needle.Length;
LukeH.. 955
如果您使用的是.NET 3.5,则可以使用LINQ在单行中执行此操作:
int count = source.Count(f => f == '/');
如果您不想使用LINQ,可以使用以下命令:
int count = source.Split('/').Length - 1;
您可能会惊讶地发现,您的原始技术似乎比其中任何一种快约30%!我刚用"/ once/on/a/time /"做了快速基准测试,结果如下:
你的原始= 12s source.Count
= 19s
source.Split = 17s
foreach(来自bobwienholt的回答)= 10s
(时间是50,000,000次迭代,因此您不太可能注意到现实世界中的差异.)
如果您使用的是.NET 3.5,则可以使用LINQ在单行中执行此操作:
int count = source.Count(f => f == '/');
如果您不想使用LINQ,可以使用以下命令:
int count = source.Split('/').Length - 1;
您可能会惊讶地发现,您的原始技术似乎比其中任何一种快约30%!我刚用"/ once/on/a/time /"做了快速基准测试,结果如下:
你的原始= 12s source.Count
= 19s
source.Split = 17s
foreach(来自bobwienholt的回答)= 10s
(时间是50,000,000次迭代,因此您不太可能注意到现实世界中的差异.)
string source = "/once/upon/a/time/"; int count = 0; foreach (char c in source) if (c == '/') count++;
必须比source.Replace()
自己快.
int count = new Regex(Regex.Escape(needle)).Matches(haystack).Count;
如果您希望能够搜索整个字符串,而不仅仅是字符:
src.Select((c, i) => src.Substring(i)) .Count(sub => sub.StartsWith(target))
读作"对于字符串中的每个字符,将该字符的其余部分从该字符开始作为子字符串;如果它以目标字符串开头,则计算它."
我做了一些研究,发现Richard Watson的解决方案在大多数情况下都是最快的.这是包含帖子中每个解决方案结果的表(除了那些使用正则表达式,因为它在解析字符串时抛出异常,如"test {test")
Name | Short/char | Long/char | Short/short| Long/short | Long/long | Inspite | 134| 1853| 95| 1146| 671| LukeH_1 | 346| 4490| N/A| N/A| N/A| LukeH_2 | 152| 1569| 197| 2425| 2171| Bobwienholt | 230| 3269| N/A| N/A| N/A| Richard Watson| 33| 298| 146| 737| 543| StefanosKargas| N/A| N/A| 681| 11884| 12486|
您可以看到,如果在短字符串(10-50个字符)中查找短子串(1-5个字符)的出现次数,则首选原始算法.
此外,对于多字符子字符串,您应该使用以下代码(基于Richard Watson的解决方案)
int count = 0, n = 0; if(substring != "") { while ((n = source.IndexOf(substring, n, StringComparison.InvariantCulture)) != -1) { n += substring.Length; ++count; } }
LINQ适用于所有集合,因为字符串只是一个字符集合,所以这个漂亮的小单行如何:
var count = source.Count(c => c == '/');
确保您using System.Linq;
位于代码文件的顶部,这.Count
是来自该命名空间的扩展方法.
string source = "/once/upon/a/time/"; int count = 0; int n = 0; while ((n = source.IndexOf('/', n)) != -1) { n++; count++; }
在我的计算机上,它比5000万次迭代的每个角色解决方案快约2秒.
2013年修订:
将字符串更改为char []并迭代它.将总时间缩短一两秒,进行50米迭代!
char[] testchars = source.ToCharArray(); foreach (char c in testchars) { if (c == '/') count++; }
这更快:
char[] testchars = source.ToCharArray(); int length = testchars.Length; for (int n = 0; n < length; n++) { if (testchars[n] == '/') count++; }
为了更好地衡量,从数组末尾迭代到0似乎是最快的,大约5%.
int length = testchars.Length; for (int n = length-1; n >= 0; n--) { if (testchars[n] == '/') count++; }
我想知道为什么会这样,并且谷歌搜索(我记得有关反向迭代更快的事情),并且发现了这个烦人地使用字符串char []技术的问题.不过,我认为逆转技巧在这方面是新的.
在C#中迭代字符串中单个字符的最快方法是什么?
这些都只适用于单字符搜索术语......
countOccurences("the", "the answer is the answer"); int countOccurences(string needle, string haystack) { return (haystack.Length - haystack.Replace(needle,"").Length) / needle.Length; }
对于更长的针头可能会变得更好......
但必须有一种更优雅的方式.:)
编辑:
source.Split('/').Length-1
在C#中,一个不错的String SubString计数器就是这个意想不到的棘手问题:
public static int CCount(String haystack, String needle) { return haystack.Split(new[] { needle }, StringSplitOptions.None).Length - 1; }
Regex.Matches(input, Regex.Escape("stringToMatch")).Count
private int CountWords(string text, string word) { int count = (text.Length - text.Replace(word, "").Length) / word.Length; return count; }
因为原始解决方案对于字符来说是最快的,我想它也适用于字符串.所以这是我的贡献.
对于上下文:我在日志文件中寻找"失败"和"成功"之类的单词.
Gr,Ben
string s = "65 fght 6565 4665 hjk"; int count = 0; foreach (Match m in Regex.Matches(s, "65")) count++;
public static int GetNumSubstringOccurrences(string text, string search) { int num = 0; int pos = 0; if (!string.IsNullOrEmpty(text) && !string.IsNullOrEmpty(search)) { while ((pos = text.IndexOf(search, pos)) > -1) { num ++; pos += search.Length; } } return num; }
对于任何想要使用String扩展方法的人来说,
这是我使用的基于最好的答案:
public static class StringExtension { ///Returns the number of occurences of a string within a string, optional comparison allows case and culture control. public static int Occurrences(this System.String input, string value, StringComparison stringComparisonType = StringComparison.Ordinal) { if (String.IsNullOrEmpty(value)) return 0; int count = 0; int position = 0; while ((position = input.IndexOf(value, position, stringComparisonType)) != -1) { position += value.Length; count += 1; } return count; } ///Returns the number of occurences of a single character within a string. public static int Occurrences(this System.String input, char value) { int count = 0; foreach (char c in input) if (c == value) count += 1; return count; } }
我认为最简单的方法是使用正则表达式.这样,您可以获得与使用myVar.Split('x')相同的拆分计数,但是在多字符设置中.
string myVar = "do this to count the number of words in my wording so that I can word it up!"; int count = Regex.Split(myVar, "word").Length;