执行代码N次和其他代码N + 1次

时间:2013-07-18 12:40:15

标签: java for-loop while-loop do-while

问题是关于while循环,其中我需要执行N次代码和其他代码N + 1次。不是关于串联字符串,我只是将它用作编码错误的简短示例。

让我通过提供一个例子来解释我的问题。

例如,我想通过将它们与“\ n”粘合来连接N + 1字符串。那么我将有N + 1行文本,但我只需要添加N次“\ n”。

这种类型的循环是否有任何样板解决方案,你必须执行N次代码和其他代码N + 1次?我不是要求连接字符串的解决方案!这只是一个(糟糕的)例子。我正在寻找一般的解决方案。

我遇到的问题是代码重复,所以为了编写我的例子,我会这样做(坏的伪代码,我知道我必须使用StringBuilder等):

String[] lines = <some array of dimension N+1>;
String total = lines[0];
for (int i = 1; i < N + 1; i++){
    total += "\n" + lines[i];
}

如果必须执行N + 1次的代码变得更大,问题会变得更糟。然后我会做类似

的事情
codeA(); // adding the line of text
for (int i = 1; i < N + 1; i++){
    codeB(); // adding the "\n"
    codeA();
}

要删除重复,你可以通过检查循环内部来做到这一点,但是我发现这非常愚蠢,因为我事先知道检查是预先确定的,因为它只会在第一次迭代时为假:

for (int i = 0; i < N + 1; i++){
    if (i > 0){
        codeB(); // adding the "\n"
    }
    codeA();
}

是否有任何解决方案,一种使用codeA()en初始化一次的while循环然后继续循环遍及codeB()和codeA()?

我想,人们之前必须遇到这种情况。只是想知道是否有任何漂亮的解决方案。

4 个答案:

答案 0 :(得分:1)

对于我的失望,我相信没有这样的结构满足你所说的条件,我会试图解释为什么(虽然我不能以严格的数学方式证明它)。

问题的要求是:

  1. 我们有两部分代码:codeA()codeB()
  2. 这两部分执行的次数不同,N和N + 1
  3. 我们希望避免在循环中添加条件
  4. 我们希望仅在必要时执行每个部分
  5. 2)是1)的直接后果。如果我们没有两部分代码,我们就不需要不同的执行次数。我们会有一个循环体。

    4)又是1)的结果。如果我们有一个循环体,则没有冗余执行。我们可以通过循环条件控制它的执行

    因此限制基本上是1)和3)。

    现在在循环中我们需要回答每次迭代的两个问题:a)我们执行codeA()吗?和b)我们执行codeB()?我们根本没有足够的信息来决定,因为我们只有一个条件(循环的条件),并且该条件将用于决定是否执行两个代码部分。

    所以我们需要打破1)和/或3)我们要么在循环中添加额外条件,要么将决策委托给其他代码(因此不再有两个部分)。

    显然,委托的一个例子可能是(我正在使用字符串连接示例):

    String [] lines = ...
    for (int i = 0; i < N; i++){
       // delegate to a utility class LineBuilder (perhaps an extension of StringBuilder) to concatenate lines
       // this class would still need to check a condition e.g. for the first line to skip the "\n"
       // since we have delegated the decisions we do not have two code parts inside the loop
       lineBuilder.addLine( lines[i] );
    }
    

    现在一个更有趣的授权案例是,如果我们可以将决定委托给数据本身(这可能值得记住)。例如:

    List<Line> lines = Arrays.asList(
                 new FirstLine("Every"),    // note this class is different
                 new Line("word"), 
                 new Line("on"), 
                 new Line("separate"), 
                 new Line("line") );
    
    StringBuffer sb = new StringBuffer();
    
    for (Line l : lines) {
        // Again the decision is delegated. Data knows how to print itself
        // Line would return: "\n" + s
        // FirstLine would return: s
        sb.append( l.getPrintVersion() );
    }
    

    当然,上述所有内容并不意味着您无法实现尝试解决问题的类。我相信虽然这超出了原始问题的范围,更不用说对于简单的循环来说是一种过度杀伤

答案 1 :(得分:0)

像这样连接字符串是个坏主意,也是一个更大的问题恕我直言。

但是要回答你的问题我会做

String sep = "";
StringBuilder sb= new StringBuilder();
for(String s: lines) {
    sb.append(sep).append(s);
    sep = "\n";
}
String all = sb.toString();

注意:通常有一种很好的方法可以避免需要创建这个String,这样就可以处理这些行。没有更多的背景,很难说。

答案 2 :(得分:0)

这种事情很常见,就像你构建sql一样。这是我遵循的模式:

String[] lines ...//init somehow;
String total = lines[0];
boolean firstTime = true;
StringBuilder sb = new StringBuilder();
for (int i = 0; i < length; i++){
    if(firstTime) firstTime = false;
    else sb.append('\n');

    sb.append(lines[i]);
}

请注意,这与第一个示例不同,这就是原因:

String[] lines = <some array of dimension N+1>;
String total = lines[0];
for (int i = 1; i < N + 1; i++){
    total += "\n" + lines[i];
}

假设你有一个[0] ='line1'和[1] ='line2'的数组 当所需的输出为:

时,最终得到line1line2 \ n

LINE1 \ nline2。

我提供的例子很清楚,但表现不佳。事实上,利用StringBuilder / Buffer可以获得更大的性能提升。拥有清晰的代码对专业人士至关重要。

答案 3 :(得分:0)

我个人大部分时间都有相同的问题,在String示例中我按照你的说法使用StringBuilder,只删除添加的字符:

StringBuilder sb = new StringBuilder();
for(int i=0; i<N; i++) {
    sb.append(array[i]).append("\n");
}
sb.delete(sb.length-1, sb.length);  // maybe check if sb contains something

在一般情况下,我认为没有其他方法可以添加你建议的方式。为了使代码更清晰,我将在for循环结束时检查:

StringBuilder sb = new StringBuilder();
for(int i=0; i<N; i++) {
    sb.append(array[i]);
    if(i < N) {
         sb.append("\n");
    }
}

但我完全同意,这是悲伤具有这种双重逻辑