【问题标题】:Splitting text into lines with maximum length将文本拆分为最大长度的行
【发布时间】:2013-03-08 12:45:15
【问题描述】:

我有一个很长的字符串,我想把它放在一个小字段中。为了实现这一点,我将字符串分成空格上的行。算法是这样的:

    public static string BreakLine(string text, int maxCharsInLine)
    {
        int charsInLine = 0;
        StringBuilder builder = new StringBuilder();
        for (int i = 0; i < text.Length; i++)
        {
            char c = text[i];
            builder.Append(c);
            charsInLine++;

            if (charsInLine >= maxCharsInLine && char.IsWhiteSpace(c))
            {
                builder.AppendLine();
                charsInLine = 0;
            }
        }
        return builder.ToString();
    }

但是当有一个短词,然后是一个较长的词时,这会中断。最大长度为 16 的“foo howcomputerwork”不会中断,但我想要它。一个想法是我期待看到下一个空格出现在哪里,但我不确定这是否会导致尽可能少的行。

【问题讨论】:

  • 您希望一行中至少 n 个字符还是最多?因为如果你想要最多 n 个字符,你需要从第n 个字符返回到一个空格。如果任何时候有一个单词超过 n 个字符,你就完蛋了。 ^_^;
  • @Corak "将文本分割成最大长度的行",这不意味着最多吗?
  • @Nolonar 是的,但代码暗示至少,所以我不确定。

标签: c# string algorithm text


【解决方案1】:

享受吧!

public static string SplitToLines(string text, char[] splitOnCharacters, int maxStringLength)
{
    var sb = new StringBuilder();
    var index = 0;

    while (text.Length > index)
    {
        // start a new line, unless we've just started
        if (index != 0)
            sb.AppendLine();

        // get the next substring, else the rest of the string if remainder is shorter than `maxStringLength`
        var splitAt = index + maxStringLength <= text.Length
            ? text.Substring(index, maxStringLength).LastIndexOfAny(splitOnCharacters)
            : text.Length - index;

        // if can't find split location, take `maxStringLength` characters
        splitAt = (splitAt == -1) ? maxStringLength : splitAt;

        // add result to collection & increment index
        sb.Append(text.Substring(index, splitAt).Trim());
        index += splitAt;
    }

    return sb.ToString();
}

注意splitOnCharactersmaxStringLength可以保存在应用的用户设置区。

【讨论】:

  • 原始帖子已经过测试和工作,不确定@DIMI 是否有机会测试他/她的编辑,但我有一种感觉 IIRC(从 2 年前 =P)你需要在每个使用此方法的行。
  • 嘿 :) 我使用相同的代码。我只是像扩展一样实现它,因为它是拆分为数组或拆分为行等方法的最流行的用法。你的回答很好,所以我做了+1,伙计。
【解决方案2】:

在写入字符串生成器之前检查字符的内容并使用当前计数or它:

    public static string BreakLine(string text, int maxCharsInLine)
    {
        int charsInLine = 0;
        StringBuilder builder = new StringBuilder();
        for (int i = 0; i < text.Length; i++)
        {
            char c = text[i];
            if (char.IsWhiteSpace(c) || charsInLine >= maxCharsInLine)
            {
                builder.AppendLine();
                charsInLine = 0;
            }
            else 
            {
                builder.Append(c);
                charsInLine++;                    
            }
        }
        return builder.ToString();
    }

【讨论】:

  • 很好地使用了字符串生成器,在将这么多字符串连接在一起时需要它。看起来它会为文本中的每个单词添加一个新行。
  • 此代码将每个单词放在新行上,无论是否行尾(基于 maxCharsInLine)。
  • @PR 根据提出的问题:“我将字符串分成空格上的行”意味着他在空格(和字符数)处分行
  • 每行一个字,string.Join(Environment.NewLine, text.Split(' ')) 更容易。此外,像@Dead.Rabit 那样,逐个字符地追加文本比以块的形式进行要慢。
【解决方案3】:

稍微更新一下代码,@dead.rabit 有时会进入循环。

 public static string SplitToLines(string text,char[] splitanyOf, int maxStringLength)
    {               
        var sb = new System.Text.StringBuilder();
        var index = 0;
        var loop = 0;
        while (text.Length > index)
        {
            // start a new line, unless we've just started
            if (loop != 0)
            {
                sb.AppendLine();
            }

            // get the next substring, else the rest of the string if remainder is shorter than `maxStringLength`
            var splitAt = 0;
            if (index + maxStringLength <= text.Length)
            {
                splitAt = text.Substring(index, maxStringLength).LastIndexOfAny(splitanyOf);
            }
            else
            {
                splitAt = text.Length - index;
            }

            // if can't find split location, take `maxStringLength` characters
            if (splitAt == -1 || splitAt == 0)
            {
                splitAt = text.IndexOfAny(splitanyOf, maxStringLength);
            }

            // add result to collection & increment index
            sb.Append(text.Substring(index, splitAt).Trim());
            if(text.Length > splitAt)
            {
                text = text.Substring(splitAt + 1).Trim();
            }
            else
            {
                text = string.Empty;
            }
            loop = loop + 1;
        }

        return sb.ToString();
    }

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2013-04-25
    • 2015-11-14
    • 2010-11-22
    • 2017-08-18
    • 2020-09-18
    • 2021-01-19
    • 2017-07-05
    相关资源
    最近更新 更多