扭转话语

时间:2014-07-10 01:35:18

标签: c#

这就是问题:

“编写一个程序,在不改变标点符号和空格的情况下反转给定句子中的单词。例如:”C#不是C ++而PHP不是Delphi“à”Delphi不是PHP而C ++不是C#“。” / p>

这是提示:
“另一个有趣的方法是通过单词之间的标点符号来分割输入文本,以便只获取文本的单词,然后用字母分割以获得文本的标点符号。因此,给出一个单词列表和一个它们之间的标点符号列表,您可以轻松地反转单词,保留标点符号。“

到目前为止,这是我的代码:

public static string ReverseWords(string str)
    {
        StringBuilder answer = new StringBuilder();
        string[] words = str.Split('.', ' ');
        char[] x = str.ToCharArray();

        string[] punctuation = str.Split(str.ToCharArray());

        for(int position = words.Length - 1; position >= 0; position--)
        {
            answer.Append(words[position]);
            answer.Append(' ');
        }

        return answer.ToString();
    }

我的问题是我解决的方式特定于给出的例子。如果还有其他分隔符,则代码无法正常工作。 那么如何使用给定的提示推广算法以使用任何分隔符?!

4 个答案:

答案 0 :(得分:1)

Method/Function的更短版本看起来像这样:

public static string ReverseWords(string str)
{       
   return String.Join(" ", str.Split('.', ' ').Reverse()).ToString();
}

答案 1 :(得分:0)

“另一个有趣的方法是通过单词之间的标点符号拆分输入文字

你在这里做到了,只需要扩展分隔符以覆盖其他标点符号

string[] words = str.Split('.', ' ');

你刚刚'。'并且'',非常简单,您需要扩展此列表以涵盖所有可能的标点符号(例如!,?等)

“为了得到文本的单词而然后用字母分割以获得文本的标点符号。”

现在对原始字符串执行相同操作,但使用所有可能的字母字符作为分隔符,而不是使用标点符号。这将删除没有空格或字母的标点符号。

棘手的部分是在新句子中放置那些讨厌的标点符号。我的解决方案可能不是最优雅的解决方案,但我会在标记之前计算n个空格,并将标记放在新句子中的n + 1个单词之后。请记住,这绝不会保证良好的语法:)

答案 2 :(得分:0)

您可以使用正则表达式解决此问题

看起来像

(\w+|[^\w])

匹配组将是单词或标点符号,然后您可以反转匹配。

答案 3 :(得分:0)

我认为,这里的诀窍在于你如何定义“单词”。像mother-in-law这样的单词,或3个单词,用连字符分隔。 That's怎么样?

出于论证的目的,我将单词定义为字母和数字序列。

首先,让我们定义一个自定义数据类型来表示我们的标记:一大块带有关联类型的文本(在我们的例子中,是'word'或'non-word'):

public enum TokenType
{
  Word    = 1 ,
  NonWord = 2 ,
}

public class Token
{

  public TokenType Type { get ; set ; }
  public string    Text { get ; set ; }

  // This helps in viewing instances in the debugger
  public override string ToString()
  {
    return string.Format( "{0}:{1}" , Type,Text ) ;
  }

}

完成后,我们需要 tokenizer 将源文本拆分为一系列令牌

static IEnumerable<Token> Tokenize( string s )
{
  StringBuilder sb = new StringBuilder() ;
  int i = 0 ;

  while ( i < s.Length )
  {
    // gobble and return a punctuation token, if there is one.
    sb.Length = 0 ;
    while ( i < s.Length && !char.IsLetterOrDigit(s[i]) )
    {
      sb.Append(s[i++]) ;
    }
    if ( sb.Length > 0 ) yield return new Token{ Type = TokenType.NonWord , Text = sb.ToString() , } ;

    // gobble the next word and return it.
    sb.Length = 0 ;
    while ( i < s.Length && char.IsLetterOrDigit( s[i] ) )
    {
      sb.Append( s[i++] ) ;
    }
    if ( sb.Length > 0 ) yield return new Token{ Type = TokenType.Word , Text = sb.ToString() , } ;
  }
}

之后,这一切都很简单:

static int Main( string[] argv )
{
  string src = "The quick brown fox, who was named Fred, jumped over a lazy Dog (named Suzy) chasing a squirrel." ;
  List<Token> tokens = new List<Token>( Tokenize( src ) ) ;

  int i = 0 ;
  int j = tokens.Count - 1 ;

  // loop, reversing words as we go.
  while ( i < j )
  {
    Token left  = tokens[i] ;
    Token right = tokens[j] ;

    if ( left.Type  != TokenType.Word ) { ++i ; continue ; }
    if ( right.Type != TokenType.Word ) { --j ; continue ; }

    // at this point, we have two words: swap them
    tokens[i++] = right     ;
    tokens[j--] = left      ;

  }

  // Finally, put everything back together
  string rev = tokens
               .Aggregate( new StringBuilder() , (b,t) => b.Append(t.Text) )
               .ToString()
               ;

  // Et, Voila!
  Console.WriteLine( "src: {0}" , src ) ;
  Console.WriteLine( "rev: {0}" , rev ) ;

  return 0 ;
}

编辑注意:以上代码吐出以下输出:

src: The quick brown fox, who was named Fred, jumped over a lazy Dog (named Suzy) chasing a squirrel.
rev: squirrel a chasing Suzy, named Dog lazy a, over jumped Fred named was (who fox) brown quick The.

进一步编辑注意:如果您想使用正则表达式,可以使用类似这样的标记符:

static IEnumerable<Token> Tokenize( string s )
{
  Regex rx = new Regex( @"(?<word>\w+)|(?<nonword>\W+)" , RegexOptions.IgnoreCase ) ;
  return rx
         .Matches( s )
         .Cast<Match>()
         .Select( m => new Token {
           Type = m.Groups["word"].Success ? TokenType.Word         : TokenType.NonWord         ,
           Text = m.Groups["word"].Success ? m.Groups["word"].Value : m.Groups["nonword"].Value ,
         }) ;
}