如何从左到右和从右到左遍历数组?
How to traverse array from both left to right and from right to left?
假设我有一个命令式算法,它保留两个索引 left
和 right
并将它们从左到右和从右到左移动
var left = 0
var right = array.length - 1
while (left < right) { .... } // move left and right inside the loop
现在我想写这个算法没有可变索引。
我怎样才能做到这一点 ?您有此类算法的示例吗?我更喜欢非递归方法。
您可以在您的列表及其反向之间映射元素对,然后从左到右遍历该对列表并在满足您的条件时继续使用:
val list = List(1, 2, 3, 4, 5)
val zipped = list zip list.reverse
val filtered = zipped takeWhile { case (a, b) => (a < b) }
filtered
的值为 List((1, 5), (2, 4))
。
现在你可以用这些元素做任何你想做的事了:
val result = filtered map {
case (a, b) =>
// do something with each left-right pair, e.g. sum them
a + b
}
println(result) // List(6, 6)
如果您需要某种上下文相关的操作(即,每个
迭代取决于前一个的结果)那么你必须
使用更强大的抽象(monad),但如果
这对你来说已经足够了。更好的方法是简单地使用递归,正如其他人所指出的,但你说那不是一个选项。
编辑:
版本没有额外的反转通道,只有 constant-time 访问 elem(length - index):
val list = List(1, 2, 3, 4, 5)
val zipped = list.view.zipWithIndex
val filtered = zipped takeWhile { case (a, index) => (a < list(list.length - 1 - index)) }
println(filtered.toList) // List((1, 0), (2, 1))
val result = filtered map {
case (elem, index) => // do something with each left-right pair, e.g. sum them
val (a, b) = (elem, list(list.length - 1 - index))
a + b
}
println(result.toList) // List(6, 6)
使用reverseIterator
:
scala> val arr = Array(1,2,3,4,5)
arr: Array[Int] = Array(1, 2, 3, 4, 5)
scala> arr.iterator.zip(arr.reverseIterator).foreach(println)
(1,5)
(2,4)
(3,3)
(4,2)
(5,1)
此函数对 IndexedSeq
集合有效,Array
可隐式转换为。
这真的取决于每次迭代需要做什么,但这里有一些事情需要考虑。
array.foldRight(0){case (elem, index) =>
if (index < array.length/2) {
/* array(index) and elem are opposite elements in the array */
/* do whatever (note: requires side effects) */
index+1
} else index // do nothing
} // ignore result
好处:只遍历数组一次,没有可变变量。
缺点:需要副作用(但在您的示例中暗示了这一点)。此外,如果它只遍历数组的一半会更好,但这需要提前突破,而 Scala 没有为此提供 easy/elegant 解决方案。
myarray = [1,2,3,4,5,6]
rmyarray = myarray[::-1]
Final_Result = []
for i in range(len(myarray)//2):
Final_Result.append(myarray[i])
Final_Result.append(rmyarray[i])
print(Final_Result)
# This is the simple approach I think .
假设我有一个命令式算法,它保留两个索引 left
和 right
并将它们从左到右和从右到左移动
var left = 0
var right = array.length - 1
while (left < right) { .... } // move left and right inside the loop
现在我想写这个算法没有可变索引。 我怎样才能做到这一点 ?您有此类算法的示例吗?我更喜欢非递归方法。
您可以在您的列表及其反向之间映射元素对,然后从左到右遍历该对列表并在满足您的条件时继续使用:
val list = List(1, 2, 3, 4, 5)
val zipped = list zip list.reverse
val filtered = zipped takeWhile { case (a, b) => (a < b) }
filtered
的值为 List((1, 5), (2, 4))
。
现在你可以用这些元素做任何你想做的事了:
val result = filtered map {
case (a, b) =>
// do something with each left-right pair, e.g. sum them
a + b
}
println(result) // List(6, 6)
如果您需要某种上下文相关的操作(即,每个 迭代取决于前一个的结果)那么你必须 使用更强大的抽象(monad),但如果 这对你来说已经足够了。更好的方法是简单地使用递归,正如其他人所指出的,但你说那不是一个选项。
编辑:
版本没有额外的反转通道,只有 constant-time 访问 elem(length - index):
val list = List(1, 2, 3, 4, 5)
val zipped = list.view.zipWithIndex
val filtered = zipped takeWhile { case (a, index) => (a < list(list.length - 1 - index)) }
println(filtered.toList) // List((1, 0), (2, 1))
val result = filtered map {
case (elem, index) => // do something with each left-right pair, e.g. sum them
val (a, b) = (elem, list(list.length - 1 - index))
a + b
}
println(result.toList) // List(6, 6)
使用reverseIterator
:
scala> val arr = Array(1,2,3,4,5)
arr: Array[Int] = Array(1, 2, 3, 4, 5)
scala> arr.iterator.zip(arr.reverseIterator).foreach(println)
(1,5)
(2,4)
(3,3)
(4,2)
(5,1)
此函数对 IndexedSeq
集合有效,Array
可隐式转换为。
这真的取决于每次迭代需要做什么,但这里有一些事情需要考虑。
array.foldRight(0){case (elem, index) =>
if (index < array.length/2) {
/* array(index) and elem are opposite elements in the array */
/* do whatever (note: requires side effects) */
index+1
} else index // do nothing
} // ignore result
好处:只遍历数组一次,没有可变变量。
缺点:需要副作用(但在您的示例中暗示了这一点)。此外,如果它只遍历数组的一半会更好,但这需要提前突破,而 Scala 没有为此提供 easy/elegant 解决方案。
myarray = [1,2,3,4,5,6]
rmyarray = myarray[::-1]
Final_Result = []
for i in range(len(myarray)//2):
Final_Result.append(myarray[i])
Final_Result.append(rmyarray[i])
print(Final_Result)
# This is the simple approach I think .