c# - 从 C# 中的句子中修剪太长的单词?

标签 c#

我有包含句子的 C# 字符串。有时这些句子没问题,有时它们只是用户生成的随机字符。我想做的是修剪这些句子中的单词。例如给定以下字符串:

var stringWithLongWords = "Here's a text with tooooooooooooo long words";

我想通过过滤器运行它:

var trimmed = TrimLongWords(stringWithLongWords, 6);

并获得每个单词最多只能包含 6 个字符的输出:

"Here's a text with tooooo long words"

关于如何以良好的性能完成这件事有什么想法吗? .NET 中有什么可以自动处理这个问题吗?

我目前正在使用以下代码:

    private static string TrimLongWords(string original, int maxCount)
    {
        return string.Join(" ", original.Split(' ').Select(x => x.Substring(0, x.Length > maxCount ? maxCount : x.Length)));
    }

这在理论上可行,但如果长单词以空格以外的分隔符结尾,它会提供错误的输出。例如:

This is sweeeeeeeeeeeeeeeet! And something more.

最终看起来像这样:

This is sweeeeeeee And something more.

更新:

好的,评论太好了,我意识到这可能有太多的“假设”。如果忘记分隔符也许会更好。相反,如果一个词被修剪,它可以用三个点显示。以下是一些单词被修剪为最多 5 个字符的示例:

现在是世界末日! -> Apoca...现在!

天启! -> 阿波卡...

!例子! -> !考试...

这是 sweeeeeeeeeeeeeeeeeet!还有更多。 -> 这太棒了……还有一些……更多。

最佳答案

编辑:由于要求发生了变化,我将继续使用正则表达式:

Regex.Replace(original, string.Format(@"(\p{{L}}{{{0}}})\p{{L}}+", maxLength), "$1...");

maxLength = 6 的输出:

Here's a text with tooooo... long words
This is sweeee...! And someth... more.

下面是旧答案,因为我喜欢这种方法,尽管它有点……凌乱:-)。


我拼凑了一个小的正则表达式替代品来做到这一点。它现在在 PowerShell 中(用于原型(prototype)制作;之后我将转换为 C#):

'Here''s a text with tooooooooooooo long words','This is sweeeeeeeeeeeeeeeet! And something more.' |
  % {
    [Regex]::Replace($_, '(\w*?)(\w)\2{2,}(\w*)',
      {
        $m = $args[0]
        if ($m.Value.Length -gt 6) {
          $l = 6 - $m.Groups[1].Length - $m.Groups[3].Length
          $m.Groups[1].Value + $m.Groups[2].Value * $l + $m.Groups[3].Value
        }
      })
  }

输出是:

Here's a text with tooooo long words
This is sweeet! And something more.

它所做的是找到遵循模式 (something)(repeated character more than two times)(别的)。对于替换,它使用一个函数来检查它的长度是否超过所需的最大长度,然后它计算重复部分的实际长度仍然适合总长度,然后仅将重复部分削减到该长度。

乱七八糟的。它将无法截断很长的单词(例如第二个测试句子中的 »something«),并且构成单词的字符集也需要更改。如果您想走那条路,请考虑这可能是一个起点,但不是最终的解决方案。

C#代码:

public static string TrimLongWords(this string original, int maxCount)
{
    return Regex.Replace(original, @"(\w*?)(\w)\2{2,}(\w*)",
        delegate(Match m) {
            var first = m.Groups[0].Value;
            var rep = m.Groups[1].Value;
            var last = m.Groups[2].Value;
            if (m.Value.Length > maxCount) {
                var l = maxCount - first.Length - last.Length;
                return first + new string(rep[0], l) + last;
            }
            return m.Value;
        });
}

字符类的更好选择可能是 \p{L},这取决于您的需要。

关于c# - 从 C# 中的句子中修剪太长的单词?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/17592296/

相关文章:

c# - 如何在新线程中调用长方法以保持 UI 在 C# 中运行

c# - 更改所有 Windows Forms 窗体上的设置

c# - 查询 XML 以提取一条记录并将数据绑定(bind)到各个文本 block

c# - LINQPad:Assert() 打印 "Fail:"并继续而不是中断

c# - 有没有办法可以延迟LINQ语句中的.Where子句?

c# - 使用 itext7 从 pdf 中的数字签名中提取电子邮件地址

c# - 为什么仅指定列的子集时 MigrationHistory 会导致 Linq 结果不同?

c# - 将文本框添加到 tablelayoutpanel 会导致文本框出现在 'random' 位置

c# - Log4Net 配置 XML

c# - 多态委托(delegate)