C# 将字符串拆分为单词边界上的两个字符串以最小化长度差异的优雅方式

C# 将字符串拆分为单词边界上的两个字符串以最小化长度差异的优雅方式,c#,string,C#,String,我现在有一个可行的解决方案,但对于如此(看似)简单的事情来说,它似乎真的很丑陋 我试着在添加一个超过一半的单词时打破它,在添加单词之前和之后都会分开,但是根据单词的长度,它要么在第一行或第二行不平衡 在复杂的修复之前,我最初遇到问题的示例输入: 输入“奶酪通心粉”和“奶酪通心粉” 应分别输出“通心粉奶酪”和“奶酪通心粉” 但更简单的解决方案要么对第一个有效,而不是第二个,要么相反 这就是我的作品,但我想知道是否有更优雅的方式来做到这一点 public string Get2LineDisplay

我现在有一个可行的解决方案,但对于如此(看似)简单的事情来说,它似乎真的很丑陋

我试着在添加一个超过一半的单词时打破它,在添加单词之前和之后都会分开,但是根据单词的长度,它要么在第一行或第二行不平衡

在复杂的修复之前,我最初遇到问题的示例输入:

输入
“奶酪通心粉”
“奶酪通心粉”

应分别输出
“通心粉
奶酪”
“奶酪
通心粉”

但更简单的解决方案要么对第一个有效,而不是第二个,要么相反

这就是我的作品,但我想知道是否有更优雅的方式来做到这一点

public string Get2LineDisplayText(string original)
{
    string[] words = original.Split(new[] {' ', '\r', '\n'}, StringSplitOptions.RemoveEmptyEntries);

    //Degenerate case with only 1 word
    if (words.Length <= 1)
    {
        return original;
    }

    StringBuilder builder = new StringBuilder();
    builder.Append(words[0]); //Add first word without prepending space
    bool addedBr = false;
    foreach (string word in words.Skip(1))
    {
        if (builder.Length + word.Length < original.Length / 2) //Word fits on the first line without passing halfway mark
        {
            builder.Append(' ' + word);
        }
        else if (!addedBr) //Adding word goes over half, need to see if it's more balanced on the 1st or 2nd line
        {
            int diffOnLine1 = Math.Abs((builder.Length + word.Length) - (original.Length - builder.Length - word.Length));
            int diffOnLine2 = Math.Abs((builder.Length) - (original.Length - builder.Length));
            if (diffOnLine1 < diffOnLine2)
            {
                builder.Append(' ' + word);
                builder.Append("<br/>");
            }
            else
            {
                builder.Append("<br/>");
                builder.Append(' ' + word);
            }
            addedBr = true;
        }
        else //Past halfway and already added linebreak, just append
        {
            builder.Append(' ' + word);
        }
    }

    return builder.ToString();
}
公共字符串Get2LineDisplayText(原始字符串)
{
string[]words=original.Split(新[]{'','\r','\n'},StringSplitOptions.RemoveEmptyEntries);
//只有一个字的退化格
if(words.Length
公共静态字符串Get2LineDisplayText(字符串原始)
{
//只有一个字的退化格
如果(!original.Any(Char.IsWhiteSpace))
{
归还原件;
}
int mid=原始长度/2;
如果(!Char.IsWhiteSpace(原始[mid]))
{
对于(int i=1;i”+原始子字符串(中间+1);
}

我试了试,得出了以下结论:

String splitInMiddle(String s) {
    int middle = s.length() / 2;
    int right = s.indexOf(" ",middle);
    int left = s.lastIndexOf(" ",middle);

    int split = right;
    if ((right < 0) || (left + right > 2*middle)) {
        split = left;
    }
    return s.substring(0, split) + "<br/>\n" + s.substring(split + 1);
}
字符串拆分中间(字符串s){
int middle=s.length()/2;
int right=s.indexOf(“,中间);
int left=s.lastIndexOf(“,中间);
int split=右;
如果((右<0)| |(左+右>2*中间)){
分裂=左;
}
返回s.substring(0,拆分)+“
\n”+s.substring(拆分+1); }
其原理是,它查找后面的第一个空间和前面的最后一个空间。 如果左边的比右边的更近,就选那个


然后用CR而不是空格粘合我想要的部分。

我想到了以下方法:

    public static string Get2Lines(string input)
    {
        //Degenerate case with only 1 word
        if (input.IndexOf(' ') == -1)
        {
            return input;
        }
        int mid = input.Length / 2;

        int first_index_after = input.Substring(mid).IndexOf(' ') + mid;
        int first_index_before = input.Substring(0, mid).LastIndexOf(' ');

        if (first_index_after - mid < mid - first_index_before)
            return input.Insert(first_index_after, "<BR />");
        else
            return input.Insert(first_index_before, "<BR />");
    }
公共静态字符串get2line(字符串输入)
{
//只有一个字的退化格
if(输入索引of(“”)=-1)
{
返回输入;
}
int mid=输入长度/2;
int first_index_after=input.Substring(mid).IndexOf(“”)+mid;
int first_index_before=input.Substring(0,mid).LastIndexOf(“”);
if(中间之后的第一个索引<中间之前的第一个索引)
返回输入。插入(在“
”之后的第一个索引); 其他的 返回输入。插入(在“
”之前的第一个索引); }
您能提供一些(简短的)吗样本输入和预期输出?@Jeff以前有过,但现在说得更清楚了。+1告诉所有人,但接受了最容易理解的一个。在理解了目标之后,这是我会想到的答案。不编译,但在修复了拼写错误并用一个单词检查了大小写之后,它就可以了行得通。所以本质上它是一个广度优先搜索最接近中间空白字符的索引。聪明。希望你不介意我用编译版本编辑它。添加了一个单词的检查。
    public static string Get2Lines(string input)
    {
        //Degenerate case with only 1 word
        if (input.IndexOf(' ') == -1)
        {
            return input;
        }
        int mid = input.Length / 2;

        int first_index_after = input.Substring(mid).IndexOf(' ') + mid;
        int first_index_before = input.Substring(0, mid).LastIndexOf(' ');

        if (first_index_after - mid < mid - first_index_before)
            return input.Insert(first_index_after, "<BR />");
        else
            return input.Insert(first_index_before, "<BR />");
    }