问题是关于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()?
我想,人们之前必须遇到这种情况。只是想知道是否有任何漂亮的解决方案。
答案 0 :(得分:1)
对于我的失望,我相信没有这样的结构满足你所说的条件,我会试图解释为什么(虽然我不能以严格的数学方式证明它)。
问题的要求是:
codeA()
和codeB()
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 \ nLINE1 \ 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");
}
}
但我完全同意,这是悲伤具有这种双重逻辑