在我正在研究的书中有一个练习:
编写一个循环,用于交换整数数组的相邻元素。例如,
Array(1,2,3,4,5)
变为Array(2,1,4,3,5)
。我的解决方案是:
var v = Array(0,1,2,3,4,5,6,7,8,9)
for (i <- 0 until v.length by 2) {
var temp = 0
temp = v(i+1); v(i+1) = v(i); v(i) = temp
}
这个算法工作正常,但没有完全利用Scala的潜力,它写得好像我用C ++写的。事实上,以下练习要求:
重复前面的赋值,但生成一个包含交换值的新数组。使用 for / yield 。
现在我尝试了:
val a = ArrayBuffer(1,2,3,4,5)
var res = for (i <- 0 until a.length by 2) yield a(i)
for (i <- 1 until a.length by 2) res(i-1)=a(i) <---------eclipse give me an error
错误是:“值更新不是scala.collection.immutable.IndexedSeq [Int] 的成员”
我该如何解决这个问题?我知道语法“for / yield”非常强大,但我不知道如何使用它。
答案 0 :(得分:3)
有一个sliding
函数可以完全满足您的需求:
(for {
i <- Array(1,2,3,4,5).sliding(2,2)
j <- i.reverse
} yield j).toArray
答案 1 :(得分:1)
我正在通过 Scala for the Impatient 来刷新我的Scala编码技能。鉴于书中这一点引入的概念,我相信作者正在寻找以下内容:
val a = Array(1, 2, 3, 4, 5)
for (i <- 0 until a.length)
yield
if (i % 2 == 0)
if (i == a.length-1) a(i)
else a(i+1)
else a(i-1)
答案 2 :(得分:0)
在您的生成器中,您使用的0 until v.length by 2
是IndexedSeq
。这是您的输入类型,yield
将为res
生成相同的集合类型。
由于immutable.IndexedSeq
是不可变的,因此无法对其进行修改。因此,不允许在{i-1更新项目的res(i-1)=a(i)
。
因此,一个选择是在继续之前将res
转换为可变集合。
通常更可取的选择是在不更新的情况下解决它。这是example使用foldLeft
,它会迭代我们的IndexedSeq
并构建一个新的扁平Array[Int]
val array = Array(1,2,3,4,5)
val result = (
for ( i <- 0 until array.length by 2)
yield
if (i < array.length-1)
Array(array(i+1), array(i))
else
Array(array(i))
).foldLeft (Array[Int]()) ((a,b) => a ++ b )
答案 3 :(得分:0)
错误是因为res
是不可变序列(Vector),无法就地更新。 Vector确实有一个updated(index: Int, elem: A)
方法,它返回一个带有更新元素的新Vector。
我不确定练习的作者是什么想法 - 使用for / yield似乎有点尴尬,但你可以使用grouped()
:
val a = Array(1,2,3,4,5) //> a : Array[Int] = Array(1, 2, 3, 4, 5)
val swapped = (for (i <- a.grouped(2)) yield i.reverse).flatten.toArray
//> swapped : Array[Int] = Array(2, 1, 4, 3, 5)
没有for / yield的更简洁的方法,也可以使用flatMap
a.grouped(2).toArray.flatMap(_.reverse)
//> res5: Array[Int] = Array(2, 1, 4, 3, 5)
答案 4 :(得分:0)
只是一种新方法:
(for (i<-0 to arr.length-2 by 2) yield Array(arr(i+1), arr(i))).flatten.toArray
答案 5 :(得分:0)
这是我的解决方案:
def swap(a: Array[Int]): Array[Int] = {
for (elem <- 0 until a.length)
yield {
if (elem % 2 == 0) {
if (elem == a.length - 1) a(elem)
else a(elem + 1)
}
else a(elem - 1)
}
}.toArray
答案 6 :(得分:0)
var result = for(j<- 0 until (a.length,2);
i<- 1 to 0 by -1;
if (j+i < a.length) )
yield a(j+i)