如何在Kotlin中编写具有两个索引值的For循环



我有如下java代码:

class Solution {
public String longestCommonPrefix(String[] strs) {
// Argument checks
if (strs == null || strs.length == 0) return "";
if (strs.length == 1) return strs[0];

StringBuilder sb = new StringBuilder();
Arrays.sort(strs);
char[] first = strs[0].toCharArray();
char[] last = strs[strs.length - 1].toCharArray();
for (int i = 0, j = 0; i < first.length && j < last.length; i++, j++) {
if (first[i] != last[j]) break;
sb.append(first[i]);
}
return sb.toString();
}
}

我的问题是如何在Kotlin中为类似循环的for (int i = 0, j = 0; i < first.length && j < last.length; i++, j++)编写?谢谢

=====更新======2022年7月29日

我想我在这里提供了一个糟糕的代码示例。。。请关注这样一个问题:我如何在Kotlin中为类似循环的for (int i = 0, j = 0; i < first.length && j < last.length; i++, j++)写作?

正如Vadik的回答所示,在这种特殊情况下,索引都取相同的值,因此只需要一个;这使得代码得到了很好的简化,并实现了整洁的Kotlin。

然而,并不总是有这样一个巧妙的解决方案。因此值得一提的是,任何旧式的for循环(在C或Java中(都可以很容易地转换为while循环

for (<initialisers>; <condition>; <updates>) {
// …loop body…
}

变为:

<initialisers>;
while (<condition>) {
// …loop body…
<updates>;
}

这种简单的转换可以对任何for循环进行,无论多么复杂。由于Kotlin有while,结果直接转化为Kotlin。

需要注意的几点:

  • 如果条件为空,则必须替换true

  • 任何循环变量现在都在循环的外部声明为,因此它们的范围更大。这带来了名称冲突的可能性(如果外部作用域已经定义了具有这些名称的变量——例如,扩展早期循环(,以及微妙的错误。因此,您可能需要重命名它们。

  • 将循环控制代码分为三个不同的地方可能不那么简洁,也更难理解。然而,对于简单、明显的环路来说,这是一个更大的问题,Kotlin已经很好地解决了这些问题——对于需要这种治疗的更复杂的环路,这可能会让它们更清楚。

在您的情况下,两个索引相同,因此您可以使用min函数来计算最后一个索引:

import kotlin.math.min
fun longestCommonPrefix() {
...
val first: CharArray = ...
val last: CharArray = ...
for (i in 0 until min(first.size, last.size)) {
if (first[i] != last[i]) break
sb.append(first[i])
}
}

您可以做的另一件普通事情是使用zip将两个值序列配对-结果将与较短的序列一样长(即只有完整的对(:

first.indices.zip(last.indices) { (a, b) ->
// do something with them - you actually get a Pair so you could skip the
// deconstruction into two variables, and just refer to it.first and it.second
}

在这种情况下,这并不是非常有用,因为两个值都是从0开始递增的,但你可以让它更通用:

println(first.indices.zip(0 until last.size step 2))
>> [(0, 0), (1, 2), (2, 4), (3, 6), (4, 8), (5, 10)]

因此,您可以定义两个单独的值序列,并在每次迭代中使用每个值的循环,这与for循环所做的类似。当然,它不一定是索引,您也可以创建要引用的实际元素的序列。

它没有那么有效(在引擎盖下创建一个ListIterables(,但为此,您确实需要直接使用for循环中的索引,或者使用gidds建议的while。(除非您确信某些内容被编译为有效的形式,例如for (i in first.indices)会编译为基本的for循环,而不使用迭代器。(


这可能违背了你所做的事情的精神,但如果你把它们保留为String,你可以这样做:

first.commonPrefixWith(last)

以防万一你不知道;(

最新更新