在Java

时间:2015-09-16 09:31:43

标签: java algorithm

我有一个长度为n的单行字符串,我希望将其分成最多3行。每行最多可以有45个字符,之后我想添加一个新行字符(" \ n")。第3行最多可以有42个字符,之后我需要包含3个点(...)如果字符串超出该字符串,那么第3行中的总字符数也是如此。

条件是新行字符不应添加到单词的中间。我该如何有效地做到这一点?此操作只是整个程序的一小部分,但会被重复调用。所以我不确定我是否真的应该为效率而烦恼。

我现在正在做的是我首先找出单词之间的空格,然后将其添加到List中。然后我遍历列表并找到3个索引,每个索引代表每行的结束词。所以第一个索引将是最接近45的空间,下一个最接近90的空间,以及最接近135的第三个索引。然后我使用这些索引来分割实际的字符串,并添加" \ n"和" ..."分别。这是我的代码:

//maxCharsPerLine will be 45
public String splitString(String input, int maxCharsPerLine){    
        String output = "";
        ArrayList<Integer> spaces = new ArrayList<Integer>();

        // Logic to figure out after which word the sentence should be split so that we don't split in middle of a word
        for(int index = 0; index < input.length(); index++){
            if(input.charAt(index)==' '){
                spaces.add(index);
            }
        }
        //add index of last word of string
        spaces.add(input.length());

        int index1 = 0; int index2 = 0; int index3 = 0;
        for(Integer index : spaces){
            // find word closest to and less than maxCharsPerLine. This index will be used to find the last word in line1
            if(index<=maxCharsPerLine)
                index1 = index;
            // find word closest to and less than 2*maxCharsPerLine. This index will be used to find the last word in line2
            else if(index<=2*maxCharsPerLine)
                index2 = index;
            // find word closest to and less than 3*maxCharsPerLine, but exclude 3 chars for adding the dots (...). This index will be used to find the last word in line3
            else if(index<=(3*maxCharsPerLine)-3)
                index3 = index;
        }

        if(input.length()>maxCharsPerLine){
            if(index1 > 0)
                output = input.substring(0, index1);
            if(index2 > 0)
                output += "\n"+input.substring(index1+1, index2);
            if(index3 > 0){
                output += "\n"+input.substring(index2+1, index3);
                if(input.length()>3*maxCharsPerLine)
                    output += "...";    
            }
        }
        //if length of input is < 45, just return the input
        else
            output = input;

        return output;
    }

不确定在哪种情况下会失败。有更好的方法吗?

感谢。

5 个答案:

答案 0 :(得分:4)

如果不考虑包含3个点,可以使用Apache Commans Lang的WordUtils.wrap方法。

WordUtils.wrap(str, 45)

答案 1 :(得分:1)

<强>代码

public class test3 {

    public static void main(String[] args) {

        String S = "The condition is that the new line should not be added in the middle of a word. How do I do this efficiently? This operation is just a small part of the entire program, but will be called repeatedly. So I'm not sure if I should actually bother about the efficiency";

        String Op = "";
        String Op1 = "";
        String Op2 = "";
        String Op3 = "";

        String Temp[] = S.split(" ");

        int max_size_1 = 45;
        int max_size_2 =  45;
        int max_size_3 =  42;

        int length = 0;

        for (int i = 0; i < Temp.length; i++) {
              length = length + Temp[i].length()+1;
           if(length <= max_size_1)   Op1 = Op1 + Temp[i]+" ";
           else  if(length <= Op1.length()+max_size_2)   Op2 = Op2 +Temp[i]+" ";
           else  if(length <= Op1.length()+Op2.length()+max_size_3)   Op3 = Op3 + Temp[i]+" ";
           else  {Op3 = Op3 +'\b' + "..."; i =Temp.length ; }  //backspace
       }

       Op = Op1+"\n"+Op2+"\n"+Op3;

       System.out.println(Op);

       System.out.println(Op1.length()+" "+Op2.length()+" "+Op3.length()+" ");
           }}

<强>输出

The condition is that the new line should 
not be added in the middle of a word. How do
I do this efficiently? This operation...
42 45 45 

答案 2 :(得分:0)

这是另一种解决方案,虽然它可能已损坏并需要进行编辑。

int sizeOfString = input.lenght();
//the maximum lenght of a String
int aPartialStringLenght = 45;
String firstString;
String secondString;
String thirdString;

for(int x = 1; x <= 3; x++){
// looks for the last space before your 45th character

//sets the lenght for the third String to max. 42characters
if(x == 3){
aPartialStringLenght = 42;
}

while(!input.charAt(aPartialStringLenght*x).equals(" ")){
aPartialStringLenght -=1;
}

switch(x){
// gets the substring till your first partialString
case 1: firstString = input.substring(0, aPartialStringlenght);
aPartialStringLenght = 45;
// gets the substring from the end of your first partialString till the end of your second partialString
case 2: secondString = input.substring(firstString.lenght(), aPartialStringLenght + firstString.lenght());
aPartialStringLenght = 45;
// gets the substring from the end of your second partialString till till the end of your third partialString + "..."
case 3 thirdString = input.substring(firstString.lenght()+secondString.lenght(), aPartialStringLenght + firstString.lenght()+ secondString.lenght() )+"..."
aPartialStringLenght = 45;
}
}

答案 3 :(得分:0)

基于surya回答

   public class test3 {

  public static void main(String[] args) {

       String S = "The condition is that the new line should not be added in the middle of a word. How do I do this efficiently? This operation is just a small part of the entire program, but will be called repeatedly. So I'm not sure if I should actually bother about the efficiency";


       String F = WordUtils.wrap(S, 45);

      String[] F1 =  F.split(System.lineSeparator());

      System.out.println(F1[0]);

      System.out.println(F1[1]);

      F1[2] = F1[2] +'\b'+'\b'+'\b'+"...";

      System.out.println(F1[2]);

       }

        }

输出

The condition is that the new line should not
be added in the middle of a word. How do I do
this efficiently? This operation is jus...

答案 4 :(得分:0)

我的建议效率很高,因为:

  • 它只需要两个对象:最终字符串和一个预先调整大小的临时StringBuilder
  • 并且它不会浪费时间进行预处理:只处理每个字符一次,并立即决定要做什么。

它也很灵活,因为所有涉及的数据都是作为参数接收的:

public final class LinesSplitter
{
    private LinesSplitter(){}

    private static final char NL='\n';

    public static String splitInLines(String text, int maxLineLength, int maxLines, String lastLineSuffix)
    {
        StringBuilder output=new StringBuilder((1 + maxLineLength) * maxLines);
        int p=0;
        int startOfLine=0;
        int lastBlank=0;
        int lastNonBlank=0;
        int len=text.length();
        String neededSuffix=text.length() > maxLineLength * maxLines
            ? lastLineSuffix
            : "";
        int lines=0;
        while (lines < maxLines && p < len)
        {
            char c=text.charAt(p);
            if (Character.isWhitespace(c))
            {
                lastBlank=p;
                lastNonBlank=1 + p;
            }
            else if (p < len)
            {
                int maxLengthForCurrentLine=getMaxLength(maxLineLength, maxLines, 1 + lines, neededSuffix);
                if (p - startOfLine == maxLengthForCurrentLine)
                {
                    output.append(text, startOfLine, lastBlank);
                    String suffix=getSuffix(maxLineLength, maxLines, 1 + lines, neededSuffix);
                    if (!suffix.isEmpty())
                    {
                        output.append(suffix);
                    }
                    else
                    {
                        output.append(NL);
                    }
                    lines++;
                    startOfLine=lastNonBlank;
                }
            }
            p++;
        }
        if (lines < maxLines && p - startOfLine > 0)
        {
            output.append(text, startOfLine, len);
        }
        return output.toString();
    }

    private final static int getMaxLength(int maxLineLength, int maxLines, int currentLine, String lastLineSuffix)
    {
        return currentLine == maxLines
            ? maxLineLength - lastLineSuffix.length()
            : maxLineLength;
    }

    private final static String getSuffix(int maxLineLength, int maxLines, int currentLine, String lastLineSuffix)
    {
        return currentLine == maxLines
            ? lastLineSuffix
            : "";
    }
}

唯一可能的缺点是它不支持几个相邻的空白。