简体   繁体   English

打印带有标点符号的反向句子 c#

[英]printing a reverse sentence with punctuation c#

I'm trying to reverse a sentence like the following: The input:我正在尝试颠倒如下句子:输入:

my name is john.我的名字是约翰。 i am 23 years old.我23岁。

The output: output:

.old years 23 am i.john is name my .old years 23 am i.john 是我的名字

I can't figure it out how to switch the dot at the end.我无法弄清楚如何在最后切换点。 I tried using Split but it always return the dot at the end of the word.我尝试使用Split ,但它总是返回单词末尾的点。

 string[] words = sentence.Split(' ');
 Array.Reverse(words);
 return string.Join(" ", words);

Add extra logic to move period ('.') before the word starts, like在单词开始之前添加额外的逻辑来移动句点('.'),例如

var sentence ="my name is john. i am 23 years old.";  //Input string
string[] words = sentence.Split(' ');                //Split sentence into words
Array.Reverse(words);                                //Revere the array of words

//If word starts with . then start your word with period and trim end.
var result = words.Select(x => x.EndsWith('.') ? $".{x.Trim('.')}" : x);  
                            //^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^This was missing
Console.WriteLine(string.Join(" ", result));

Try online在线尝试

You can try combination of Linq and Regular Expressions :您可以尝试Linq正则表达式的组合:

  using System.Linq;
  using System.Text.RegularExpressions;

  ...

  string source = "my name is john. i am 23 years old.";

  // .old years 23 am i .john is name my
  string result = string.Join(" ", Regex
    .Matches(source, @"\S+")
    .Cast<Match>()
    .Select(m => Regex.Replace(m.Value, @"^(.*?)(\p{P}+)$", "$2$1"))
    .Reverse());

Here we use two patterns: a simple one "\S+" which matches any characters which are not whitespaces.这里我们使用两种模式:一种简单的"\S+" ,它匹配任何不是空格的字符。 The next pattern ^(.*?)(\p{P}+)$ worth explaining:下一个模式^(.*?)(\p{P}+)$值得解释:

^(.*?)(\p{P}+)$

here这里

^        - anchor, start of the string 
(.*?)    - group #1: any symbols, but as few as possible
(\p{P}+) - group #2: one or more punctuation symbols
$        - anchor, end of the string

and when matched we swap these groups: "&2&1"当匹配时,我们交换这些组: "&2&1"

Demo:演示:

private static string Solve(string source) => string.Join(" ", Regex
  .Matches(source, @"\S+")
  .Cast<Match>()
  .Select(m => Regex.Replace(m.Value, @"^(.*?)(\p{P}+)$", "$2$1"))
  .Reverse());

...

string[] tests = new string[] {
  "my name is john. i am 23 years old.",
  "It's me, here am I!",
  "Test...",
};

string report = string.Join(Environment.NewLine, tests
  .Select(test => $"{test,-35} => {Solve(test)}"));

Console.Write(report);

Outcome:结果:

my name is john. i am 23 years old. => .old years 23 am i .john is name my
It's me, here am I!                 => !I am here ,me It's
Test...                             => ...Test

You are reversing words separated by space (in old. the point is part of the word).您正在反转由空格分隔的单词(在old.点是单词的一部分)。 If you want to reverse the points too you want to consider them as words (sperated by space):如果您也想反转这些点,您想将它们视为单词(由空格分隔):

public static class TextExtensions
{
    public static string PointTrick(this string str) => str.Replace(".", " .");

    public static string PointUntrick(this string str) => str.Replace(". ", ".");

    public static string ReverseWords(this string str) => string.Join(" ", str.Split(" ").Reverse());
}

Those tests pass.这些测试通过了。

[TestClass]
public class SOTests
{
    private string GetReversedWithPointTrick(string input) => input.PointTrick().ReverseWords().PointUntrick();


    [TestMethod]
    public void ReverseWordsTest()
    {
        var sut = "three two. one";
        var expected = "one two. three";

        var result = sut.ReverseWords();

        Assert.AreEqual(expected, result);
    }

    [TestMethod]
    public void ReverseWords_PointTrick_Test()
    {
        var sut = "my name is john. i am 23 years old.";
        var expected = ".old years 23 am i .john is name my";

        var result = GetReversedWithPointTrick(sut);

        Assert.AreEqual(expected, result);
    }
}

Because someone always has to post a LINQ version of these things因为总有人要贴出LINQ版的这些东西

sentence.Split().Reverse.Select(w => w[^1] == '.' ? ('.' + w[..^1]) : w);

Split without any argument splits on whitespace, Reverse is a LINQ thing that reverses the input and then we just have a bit of logic that asks if the last (^1 is from the indexes and ranges feature of c# 9, meaning "one from the end") char is a dot, move it to the start (concat a dot plus all the string up to 1 from the end) othwise just output the word..没有任何参数的拆分在空格上拆分,Reverse 是一个 LINQ 事物,它反转输入,然后我们只有一些逻辑询问最后一个(^1 是否来自 c# 9 的索引和范围功能,意思是“来自end") char 是一个点,将它移到开头(连接一个点加上从末尾到 1 的所有字符串)否则只是 output 这个词..

And all that remains is to string join it, which you know how to do: string.Join(" ", ...)剩下的就是把它串起来,你知道怎么做: string.Join(" ", ...)

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

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