简体   繁体   English

在字符串开头找到字母,后跟空格

[英]find letter at the beginning of the string followed by space

I want to Write a method which will count the letters "a" or "A". 我想写一个方法来计算字母“ a”或“ A”。 The "a" can be either at the beginning of the string followed by space, or anywhere in the string surrounded by spaces. “ a”可以在字符串的开头,后跟空格,或者在字符串中被空格包围的任何位置。 the result should be 2 but I am getting 5 with my code, how do i modify the code so it detects the space before and after a? 结果应该是2,但是我的代码得到5,如何修改代码,以便它检测a之前和之后的空间?

using System;

namespace Hi
{
    class Program
    {
        static void Main(string[] args)
        {
            string t1 = "A book was lost. There is a book on the table. Is that the book?";

            Console.WriteLine(t1);
            Console.WriteLine(" - Found {0} articles, should be 2.", CountArticles(t1));
            Console.ReadKey();
        }

        static int CountArticles(string text)
        {
            int count = 0;

            {
                for (int i = 0; i < text.Length; ++i)
                {
                    if (text[i] == 'a' || text[i] == 'A')
                    {
                        ++count;
                    }
                }            
                return count;
        }
    }
}
}

I suggest using regular expressions in order to count all the matches; 我建议使用正则表达式来计算所有匹配项。 something like this: 像这样的东西:

  using System.Text.RegularExpressions;

  ... 

  string t1 = "A book was lost. There is a book on the table. Is that the book?";

  int count = Regex.Matches(t1, @"\bA\b", RegexOptions.IgnoreCase).Count;

In case you insist on for loop, you have to check for spaces : 如果您坚持使用for循环,则必须检查空格

  static int CountArticles(string text)
  {
      int count = 0;

      for (int i = 0; i < text.Length; ++i)
      {
          if (text[i] == 'a' || text[i] == 'A')
          {
             // So we have a or A, now we have to check for spaces:
             if (((i == 0) || char.IsWhiteSpace(text[i - 1])) &&
                 ((i == text.Length - 1) || char.IsWhiteSpace(text[i + 1])))
                ++count;
           }
       }            

       return count;
  } 

Personally, I'm a huge fan of simple DFA state machines. 就个人而言,我非常喜欢简单的DFA状态机。 Feels strange, so I'll explain why... It all boils down to a few reasons: 感觉很奇怪,所以我将解释原因...归结为以下几个原因:

  1. DFA's are incredibly fast; DFA的速度非常快; if you do parsing like I do, there's a high chance that you'll throw a lot of data at this code. 如果您像我一样进行解析,则很有可能在此代码中抛出大量数据。 Performance matters. 性能很重要。
  2. DFA's are very easy to unit test; DFA非常容易进行单元测试; only thing you need to do is to make sure you test all states and transitions. 您唯一需要做的就是确保测试所有状态和转换。
  3. Code coverage reports on DFA's are very usable. DFA的代码覆盖率报告非常有用。 It doesn't guarantee that you're design is correct, but if it is, it'll work. 它不能保证您的设计是正确的,但是如果是正确的,那么它将起作用。 You'll definitely get a lot more information from it than coverage on a Regex. 您肯定会从中获得比Regex涵盖的更多信息。

The main disadvantages are: 主要缺点是:

  1. That they require more work to build. 他们需要更多的工作来构建。 (*) (*)
  2. That you should use a piece of paper to think them out (and document them as such for other people). 您应该使用一张纸来思考它们(并像其他人那样记录下来)。

Once you get the idea, it's easy to construct a DFA. 一旦您有了主意,就可以轻松构建DFA。 Grab a piece of paper, think about the possible states of your program (draw circles), and transitions between them (arrows between the circles). 拿一张纸,考虑一下程序的可能状态(画圆圈),并在它们之间进行转换(圆圈之间的箭头)。 Last, think about what should happen when. 最后,考虑一下什么时候会发生。

The translation to code is pretty much 1:1. 转换为代码几乎是1:1。 Using a switch is just one implementation - there are other ways to do this. 使用开关只是一种实现方式-还有其他方式可以做到这一点。 Anyways, without further interruption, here goes: 无论如何,这里没有进一步的干扰:

enum State
{
    SpaceEncountered,
    ArticleEncountered,
    Default
};

static int CountArticles(string text)
{
    int count = 0;
    State state = State.SpaceEncountered; // start of line behaves the same

    for (int i = 0; i < text.Length; ++i)
    {
        switch (state)
        {
            case State.SpaceEncountered:
                if (text[i] == 'a' || text[i] == 'A')
                {
                    state = State.ArticleEncountered;
                }
                else if (!char.IsWhiteSpace(text[i]))
                {
                    state = State.Default;
                }
                break;

            case State.ArticleEncountered:
                if (char.IsWhiteSpace(text[i]))
                {
                    ++count;
                    state = State.SpaceEncountered;
                }
                else
                {
                    state = State.Default;
                }
                break;
            case State.Default: // state 2 = 
                if (char.IsWhiteSpace(text[i]))
                {
                    state = State.SpaceEncountered;
                }
                break;
        }
    }

    // if we're in state ArticleEncountered, the next is EOF and we should count one extra
    if (state == State.ArticleEncountered)
    {
        ++count;
    }
    return count;
}

static void Main(string[] args)
{
    Console.WriteLine(CountArticles("A book was lost. There is a book on the table. Is that the book?"));
    Console.ReadLine();
}

(*) Now, I see people pondering, well that's a lot of code for such an easy problem. (*)现在,我看到人们在思考,好吧,这么一个简单的问题的代码很多。 Yeah, that's very true, which is why there are ways to generate DFA's. 是的,这是真的,这就是为什么存在生成DFA的方法的原因。 The most usual ways to do this are to construct a lexer or a regex. 最常用的方法是构造一个词法分析器或正则表达式。 For this toy problem that's a bit much, but perhaps you're real problem is a bit larger... 这个玩具问题有点多,但也许您真正的问题要大一些...

像这样使用String.Split

int count = text.Split(' ').Count(c => c == "a" || c == "A");

You may also use TextInfo class to Make string as a Title Case so the beginning of the string or followed by space would be 您还可以使用TextInfo类将字符串作为“ 标题大小写”,以便字符串的开头或后跟空格

A Book Was Lost. 一本书丢了。 There Is A Book On The Table. 桌上有一本书。 Is That The Book? 那是书吗?

Now you can use your function CountArticles to count your Character 现在您可以使用CountArticles函数来计算角色

  namespace Hi
{
    class Program
    {
        static void Main(string[] args)
        {


    string t1 = "A book was lost. There is a book on the table. Is that the book?";

            Console.WriteLine(t1);
            Console.WriteLine(" - Found {0} articles, should be 2.", CountArticles(t1));
            Console.ReadKey();
        }

        static int CountArticles(string text)
        {
            int count = 0;

            // Here you may also try TextInfo
            //Make string as a Title Case
            //the beginning of the string OR followed by space would be now  'A'
            TextInfo textInfo = new CultureInfo("en-US", false).TextInfo;
            text = textInfo.ToTitleCase(text); 


            {
                for (int i = 0; i < text.Length; ++i)
                {
                    if (text[i] == 'A')
                    {
                        ++count;
                    }
                }
                return count;
            }
        }
    }
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM