【问题标题】:Truncate string on whole words in .NET C#在.NET C#中截断整个单词的字符串
【发布时间】:2010-12-09 11:47:57
【问题描述】:

我正在尝试在 C# 中截断一些长文本,但我不希望我的字符串在某个单词中被截断。有没有人有一个函数可以用来截断单词末尾的字符串?

例如:

"This was a long string..."

不是:

"This was a long st..."

【问题讨论】:

  • 你能给出你当前的截断解决方案吗?
  • @Cloud Just .Substring(0, )
  • 如果 大于实际字符串,子字符串会抛出异常,需要额外检查。

标签: c# .net string truncate


【解决方案1】:

试试下面的。这是相当初级的。只需找到从所需长度开始的第一个空格。

public static string TruncateAtWord(this string value, int length) {
    if (value == null || value.Length < length || value.IndexOf(" ", length) == -1)
        return value;

    return value.Substring(0, value.IndexOf(" ", length));
}

【讨论】:

  • 完美!而且看不到正则表达式:)
  • 在所需长度之前找到第一个空格可能有意义吗?否则,您必须猜测所需的长度?
  • 不使用正则表达式也应该是-1 ;)
  • @string 的用法是不必要的:在这种情况下,它是不必要且令人困惑的。该参数可以很容易地命名为str。如果不是这样,我会赞成这个答案。
  • 我不同意使用缩写“str”——我认为缩写总是使代码的可读性降低。 +1 评论改为使用“价值”。
【解决方案2】:

感谢您的回答戴夫。我已经稍微调整了函数,这就是我正在使用的......除非有更多的 cmets ;)

public static string TruncateAtWord(this string input, int length)
{
    if (input == null || input.Length < length)
        return input;
    int iNextSpace = input.LastIndexOf(" ", length, StringComparison.Ordinal);
    return string.Format("{0}…", input.Substring(0, (iNextSpace > 0) ? iNextSpace : length).Trim());
}

【讨论】:

  • 除此之外,我现在还从这个函数中调用另一个字符串实用函数,它会去除任何 HTML 标记(使用 RegEx)。这最大限度地降低了由于截断而导致 HTML 损坏的风险,因为所有字符串都是纯文本。
  • 请注意,此方法查找第一个空格AFTER 指定的长度值,几乎总是导致结果字符串比该值长。要查找长度之前的最后一个空格,只需在计算 iNextSpace 时替换 input.LastIndexOf(" ", length)。
  • CBono 的评论 +100 - 这需要在之前!在这种情况下,像这个一样长的单词你将有非常长的字符串,远远超出你想要的长度!
  • 您可以添加一个省略号字符。 “……”
  • 在第 5 行我建议使用:int iNextSpace = input.LastIndexOf(" ", length, System.StringComparison.Ordinal); 用于语言特定字符
【解决方案3】:

我的贡献:

public static string TruncateAtWord(string text, int maxCharacters, string trailingStringIfTextCut = "&hellip;")
{
    if (text == null || (text = text.Trim()).Length <= maxCharacters) 
      return text;

    int trailLength = trailingStringIfTextCut.StartsWith("&") ? 1 
                                                              : trailingStringIfTextCut.Length; 
    maxCharacters = maxCharacters - trailLength >= 0 ? maxCharacters - trailLength 
                                                     : 0;
    int pos = text.LastIndexOf(" ", maxCharacters);
    if (pos >= 0)
        return text.Substring(0, pos) + trailingStringIfTextCut;

    return string.Empty;
}

这是我在我的项目中使用的,带有可选的尾随。文本永远不会超过 maxCharacters + 尾随文本长度。

【讨论】:

    【解决方案4】:

    如果您使用的是 Windows 窗体,则在 Graphics.DrawString 方法中,StringFormat 中有一个选项可以指定字符串是否应被截断,如果它不适合指定的区域。这将根据需要处理添加省略号。

    http://msdn.microsoft.com/en-us/library/system.drawing.stringtrimming.aspx

    【讨论】:

    • 这是一个 ASP.Net 页面,但我做了一些 Win Forms 的工作,很高兴知道!
    【解决方案5】:

    我把你的方法更进一步:

    public string TruncateAtWord(string value, int length)
    {
        if (value == null || value.Trim().Length <= length)
            return value;
    
        int index = value.Trim().LastIndexOf(" ");
    
        while ((index + 3) > length)
            index = value.Substring(0, index).Trim().LastIndexOf(" ");
    
        if (index > 0)
            return value.Substring(0, index) + "...";
    
        return value.Substring(0, length - 3) + "...";
    }
    

    我正在使用它来截断推文。

    【讨论】:

    • 我会考虑将“...”提取到一个常量中,因为如果您决定更改它,您现在必须在 4 个位置更新它(如果您包含数字 3)
    【解决方案6】:

    这个解决方案也有效(从 myString 获取前 10 个单词):

    String.Join(" ", myString.Split(' ').Take(10))
    

    【讨论】:

    • 这实际上非常简洁。它不适合某些场景(例如word.),但通常是一种很好的可读方法。
    【解决方案7】:

    考虑到不仅仅是空格分隔符(例如,单词可以用句点分隔,后跟换行符,后跟制表符等),以及其他几种边缘情况,这里是一种适当的扩展方法:

        public static string GetMaxWords(this string input, int maxWords, string truncateWith = "...", string additionalSeparators = ",-_:")
        {
            int words = 1;
            bool IsSeparator(char c) => Char.IsSeparator(c) || additionalSeparators.Contains(c);
    
            IEnumerable<char> IterateChars()
            {
                yield return input[0];
    
                for (int i = 1; i < input.Length; i++)
                {
                    if (IsSeparator(input[i]) && !IsSeparator(input[i - 1]))
                        if (words == maxWords)
                        {
                            foreach (char c in truncateWith)
                                yield return c;
    
                            break;
                        }
                        else
                            words++;
    
                    yield return input[i];
                }
            }
    
            return !input.IsNullOrEmpty()
                ? new String(IterateChars().ToArray())
                : String.Empty;
        }
    

    【讨论】:

    • 这是为我解决它的唯一版本,处理报价......例如..“用户将'约会日期'更新为 2020-10-28T12:00:00.000Z 从 2020-10- 28T04:00:00.000Z"
    【解决方案8】:

    简化,添加中继字符选项并使其成为扩展。

        public static string TruncateAtWord(this string value, int maxLength)
        {
            if (value == null || value.Trim().Length <= maxLength)
                return value;
    
            string ellipse = "...";
            char[] truncateChars = new char[] { ' ', ',' };
            int index = value.Trim().LastIndexOfAny(truncateChars);
    
            while ((index + ellipse.Length) > maxLength)
                index = value.Substring(0, index).Trim().LastIndexOfAny(truncateChars);
    
            if (index > 0)
                return value.Substring(0, index) + ellipse;
    
            return value.Substring(0, maxLength - ellipse.Length) + ellipse;
        }
    

    【讨论】:

    • 这根本无法按预期工作。请至少在此处发布任何内容之前进行完整性检查。
    【解决方案9】:

    这就是我想出的。这是为了让句子的其余部分也分块。

    public static List<string> SplitTheSentenceAtWord(this string originalString, int length)
        {
            try
            {
                List<string> truncatedStrings = new List<string>();
                if (originalString == null || originalString.Trim().Length <= length)
                {
                    truncatedStrings.Add(originalString);
                    return truncatedStrings;
                }
                int index = originalString.Trim().LastIndexOf(" ");
    
                while ((index + 3) > length)
                    index = originalString.Substring(0, index).Trim().LastIndexOf(" ");
    
                if (index > 0)
                {
                    string retValue = originalString.Substring(0, index) + "...";
                    truncatedStrings.Add(retValue);
    
                    string shortWord2 = originalString;
                    if (retValue.EndsWith("..."))
                    {
                        shortWord2 = retValue.Replace("...", "");
                    }
                    shortWord2 = originalString.Substring(shortWord2.Length);
    
                    if (shortWord2.Length > length) //truncate it further
                    {
                        List<string> retValues = SplitTheSentenceAtWord(shortWord2.TrimStart(), length);
                        truncatedStrings.AddRange(retValues);
                    }
                    else
                    {
                        truncatedStrings.Add(shortWord2.TrimStart());
                    }
                    return truncatedStrings;
                }
                var retVal_Last = originalString.Substring(0, length - 3);
                truncatedStrings.Add(retVal_Last + "...");
                if (originalString.Length > length)//truncate it further
                {
                    string shortWord3 = originalString;
                    if (originalString.EndsWith("..."))
                    {
                        shortWord3 = originalString.Replace("...", "");
                    }
                    shortWord3 = originalString.Substring(retVal_Last.Length);
                    List<string> retValues = SplitTheSentenceAtWord(shortWord3.TrimStart(), length);
    
                    truncatedStrings.AddRange(retValues);
                }
                else
                {
                    truncatedStrings.Add(retVal_Last + "...");
                }
                return truncatedStrings;
            }
            catch
            {
                return new List<string> { originalString };
            }
        }
    

    【讨论】:

      【解决方案10】:

      我用这个

      public string Truncate(string content, int length)
          {
              try
              {
                  return content.Substring(0,content.IndexOf(" ",length)) + "...";
              }
              catch
              {
                  return content;
              }
          }
      

      【讨论】:

        猜你喜欢
        • 2019-01-03
        • 1970-01-01
        • 1970-01-01
        • 2013-04-04
        • 2019-07-30
        • 2011-10-02
        • 1970-01-01
        • 2021-10-28
        • 1970-01-01
        相关资源
        最近更新 更多