当前位置:  开发笔记 > 编程语言 > 正文

你如何计算字符串中字符串(实际上是字符)的出现次数?

如何解决《你如何计算字符串中字符串(实际上是字符)的出现次数?》经验,为你挑选了16个好方法。

我正在做一些事情,我意识到我想要计算/我能在字符串中找到多少,然后它让我感到震惊,有几种方法可以做到,但无法决定最好的(或最简单的)是什么.

目前我正在做的事情如下:

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次迭代,因此您不太可能注意到现实世界中的差异.)



1> LukeH..:

如果您使用的是.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次迭代,因此您不太可能注意到现实世界中的差异.)


听到我的代码比任何东西都快!
请注意,Count和Split解决方案仅在您对字符进行计数时才有效.他们不会使用字符串,就像OP的解决方案那样.
这种行为可能是因为VS2010在新的类文件中自动包含System.Linq,VS2008可能没有.命名空间需要用于智能感知才能工作.
这似乎是一个不同问题的答案:"你如何计算字符串中char的出现?"
是的,VS隐藏了字符串类的LINQ扩展方法.我猜他们认为开发人员不希望所有这些扩展方法出现在字符串类中.可能是一个明智的决定.
`f =='\'`是关于字符串中的字符,而不是字符串中的字符串
另外值得注意的是,如果使用System.GC.GetTotalMemory(false)监视内存使用情况.重复5000万次迭代测试,我看到在LINQ之后准备好垃圾收集大约2,000,000个字节.随着foreach循环......零.如果您处于高重复代码区域,LINQ可能看起来很光滑,但是要上学.

2> bobwienholt..:
string source = "/once/upon/a/time/";
int count = 0;
foreach (char c in source) 
  if (c == '/') count++;

必须比source.Replace()自己快.


通过切换到for而不是foreach,你可以获得微小的改进,但只是微小的一点点.
不.问题要求计算字符串的出现,而不是字符.
这是计算字符串中的字符.标题是关于计算字符串中的字符串
@Mark刚刚使用for循环对其进行了测试,它实际上比使用foreach慢。可能是因为边界检查?(时间为1.65秒,而500万次迭代为2.05。)
虽然问题是要求字符串中的字符串,但是发布的示例问题OP实际上只是一个字符,在这种情况下我会称这个答案仍然是一个有效的解决方案,因为它显示了一种更好的方法(字符搜索而不是字符串搜索)解决手头的问题.

3> Yet Another ..:
int count = new Regex(Regex.Escape(needle)).Matches(haystack).Count;


+1 - 在某些情况下,您可能想要添加`RegexOptions.IgnoreCase`.
这不是很低吗?
正则表达式的开销并不理想,加上"我真的不想为此挖出RegEx,是吗?"

4> mqp..:

如果您希望能够搜索整个字符串,而不仅仅是字符:

src.Select((c, i) => src.Substring(i))
    .Count(sub => sub.StartsWith(target))

读作"对于字符串中的每个字符,将该字符的其余部分从该字符开始作为子字符串;如果它以目标字符串开头,则计算它."


**SUPER SLOW!***在html页面上尝试过,与此页面上的其他方法相比花费了大约2分钟花了2秒钟.答案是对的; 它太慢而无法使用.*
为我的210000个字符串字符抛出OutOfMemoryException.
请注意,这个速度很慢的原因是它创建了n个字符串,因此分配大约n ^ 2/2个字节.
同意,太慢了.我是linq风格解决方案的忠实粉丝,但这一点并不可行.

5> tsionyx..:

我做了一些研究,发现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;
    }
}


只是为了指出其他人,如果空的话需要检查搜索值,否则你将进入无限循环.
也许它只是我,但是对于`source ="aaa"substring ="aa"`我希望得到2,而不是1.要"修复"这个,将`n + = substring.Length`改为`n ++`

6> Judah Gabrie..:

LINQ适用于所有集合,因为字符串只是一个字符集合,所以这个漂亮的小单行如何:

var count = source.Count(c => c == '/');

确保您using System.Linq;位于代码文件的顶部,这.Count是来自该命名空间的扩展方法.


@Whatsit:你可以用左手输入'var'而'int'需要双手;)
`int`字母全部驻留在home键中,而`var`则不存在.呃..等等,我正在使用Dvorak
在那里使用var真的值得吗?有没有机会将Count替换为不返回int的东西?
@JudahGabrielHimango我会争辩说,当变量类型很明显时(为了简洁和一致),应该_特别是使用var
@BDotA确保你有'使用System.Linq;' 在您的文件的顶部.此外,intellisense可能会隐藏.Count调用,因为它是一个字符串.即使这样,它也会编译并运行得很好.

7> Richard Wats..:
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#中迭代字符串中单个字符的最快方法是什么?



8> ZombieSheep..:

这些都只适用于单字符搜索术语......

countOccurences("the", "the answer is the answer");

int countOccurences(string needle, string haystack)
{
    return (haystack.Length - haystack.Replace(needle,"").Length) / needle.Length;
}

对于更长的针头可能会变得更好......

但必须有一种更优雅的方式.:)



9> Brian Rudolp..:

编辑:

source.Split('/').Length-1


这将在堆上执行至少n个字符串分配,加上(可能)少量阵列重新调整大小 - 所有这些只是为了得到计数?非常低效,不能很好地扩展,不应该在任何重要的代码中使用.
这就是我的工作.和`source.Split(new [] {"//"},StringSplitOptions.None).Count - 1`用于多字符分隔符.

10> Dave..:

在C#中,一个不错的String SubString计数器就是这个意想不到的棘手问题:

public static int CCount(String haystack, String needle)
{
    return haystack.Split(new[] { needle }, StringSplitOptions.None).Length - 1;
}



11> cederlof..:
Regex.Matches(input,  Regex.Escape("stringToMatch")).Count



12> 小智..:
private int CountWords(string text, string word) {
    int count = (text.Length - text.Replace(word, "").Length) / word.Length;
    return count;
}

因为原始解决方案对于字符来说是最快的,我想它也适用于字符串.所以这是我的贡献.

对于上下文:我在日志文件中寻找"失败"和"成功"之类的单词.

Gr,Ben


只是不要为“ word”变量传递一个空字符串(除以零误差)。

13> 小智..:
string s = "65 fght 6565 4665 hjk";
int count = 0;
foreach (Match m in Regex.Matches(s, "65"))
  count++;


或Regex.Matches(s,"65").计数^ _ ^

14> user460847..:
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;
}



15> WhoIsRich..:

对于任何想要使用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;
    }
}



16> 小智..:

我认为最简单的方法是使用正则表达式.这样,您可以获得与使用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;

推荐阅读
爱唱歌的郭少文_
这个屌丝很懒,什么也没留下!
DevBox开发工具箱 | 专业的在线开发工具网站    京公网安备 11010802040832号  |  京ICP备19059560号-6
Copyright © 1998 - 2020 DevBox.CN. All Rights Reserved devBox.cn 开发工具箱 版权所有