8

I am trying to swap every pair of values in my array using for and yield and so far I am very unsuccessful. What I have tried is as follows:

val a = Array(1,2,3,4,5) //What I want is Array(2,1,4,3,5)

for(i<-0 until (a.length-1,2),r<- Array(i+1,i)) yield r

The above given snippet returns the vector 2,1,4,3(and the 5 is omitted)

Can somebody point out what I am doing wrong here and how to get the correct reversal using for and yields?

Thanks

sc_ray
  • 7,803
  • 11
  • 63
  • 100

9 Answers9

41
a.grouped(2).flatMap(_.reverse).toArray

or if you need for/yield (much less concise in this case, and in fact expands to the same code):

(for {b <- a.grouped(2); c <- b.reverse} yield c).toArray
Rogach
  • 26,050
  • 21
  • 93
  • 172
17

It would be easier if you didin't use for/yield:

a.grouped(2)
  .flatMap{ 
    case Array(x,y) => Array(y,x)
    case Array(x) => Array(x)
  }.toArray // Array(2, 1, 4, 3, 5)
dhg
  • 52,383
  • 8
  • 123
  • 144
  • 3
    This is probably a mature way of doing things. I am learning scala and was wondering if the same could be accomplished using for/yield. – sc_ray Apr 15 '12 at 00:30
  • @sc_ray, The `for/yield` construction makes things nicer a lot of the time, but this isn't a great match for it. – dhg Apr 15 '12 at 00:45
  • If original task comes from Horstman's book, it ask us to **swap** elements in array, NOT CREATE NEW ONE. But theese solutions are more elegant than yield(ing) – Timur Milovanov Jul 20 '18 at 08:26
  • Sory, there are both task: with swap elements with existing array and while creating new one (with map-function) – Timur Milovanov Jul 20 '18 at 08:57
9

I don't know if the OP is reading Scala for the Impatient, but this was exercise 3.3 .

I like the map solution, but we're not on that chapter yet, so this is my ugly implementation using the required for/yield. You can probably move some yield logic into a guard/definition.

for( i <- 0 until(a.length,2); j <- (i+1).to(i,-1) if(j<a.length) ) yield a(j)

I'm a Java guy, so I've no confirmation of this assertion, but I'm curious what the overhead of the maps/grouping and iterators are. I suspect it all compiles down to the same Java byte code.

Joseph Lust
  • 19,340
  • 7
  • 85
  • 83
1

Another simple, for-yield solution:

def swapAdjacent(array: ArrayBuffer[Int]) = {
    for (i <- 0 until array.length) yield (
        if (i % 2 == 0)
            if (i == array.length - 1) array(i) else array(i + 1)
        else array(i - 1)
    )
}
Haris Osmanagić
  • 1,249
  • 12
  • 28
0

Here is my solution

  def swapAdjacent(a: Array[Int]):Array[Int] =
    (for(i <- 0 until a.length) yield
      if (i%2==0 && (i+1)==a.length) a(i) //last element for odd length
      else if (i%2==0) a(i+1)
      else a(i-1)
    ).toArray

https://github.com/BasileDuPlessis/scala-for-the-impatient/blob/master/src/main/scala/com/basile/scala/ch03/Ex03.scala

0

If you are doing exercises 3.2 and 3.3 in Scala for the Impatient here are both my answers. They are the same with the logic moved around.

/** Excercise 3.2 */
for (i <- 0 until a.length if i % 2 == 1) {val t = a(i); a(i) = a(i-1); a(i-1) = t }
/** Excercise 3.3 */
for (i <- 0 until a.length) yield { if (i % 2 == 1) a(i-1) else if (i+1 <= a.length-1) a(i+1) else a(i) }
ChinnoDog
  • 1
  • 1
0
for (i <- 0 until arr.length-1 by 2) { val tmp = arr(i); arr(i) = arr(i+1); arr(i+1) = tmp }

I have started to learn Scala recently and all solutions from the book Scala for the Impatient (1st edition) are available at my github:

Chapter 2 https://gist.github.com/carloscaldas/51c01ccad9d86da8d96f1f40f7fecba7

Chapter 3 https://gist.github.com/carloscaldas/3361321306faf82e76c967559b5cea33

Carlos Caldas
  • 806
  • 11
  • 12
0

I have my solution, but without yield. Maybe someone will found it usefull.

def swap(x: Array[Int]): Array[Int] = {
    for (i <- 0 until x.length-1 by 2){
      var left = x(i)
      x(i) = x(i+1)
      x(i+1) = left
    }
    x
  }
Artem Vlasenko
  • 115
  • 1
  • 1
  • 7
0

Assuming array is not empty, here you go:

val swapResult = for (ind <- arr1.indices) yield {
  if (ind % 2 != 0) arr1(ind - 1)
  else if (arr1(ind) == arr1.last) arr1(ind)
  else if (ind % 2 == 0) arr1(ind + 1)
}
Seth B
  • 1,014
  • 7
  • 21
Samip
  • 1
  • 1
  • @jwvh I found few of the solution were throwing exceptions in case of odd numbers of variables hence the modification was done. I can see fi there is an empty array defined than the method .indices might will produce compile time error. – Samip Feb 14 '21 at 01:16
  • `.indices` on an empty `Array` does **not** produce a compile time error. It doesn't produce a run time error. It works correctly without error. – jwvh Feb 14 '21 at 01:31
  • @jwvh Thank you just figured that in case if we don't define the type of array during declaration i.e. val arr1: Array[] = Array() then .indices works but when we depend on type inference i.e. val arr1 = Array() then the error exists – Samip Feb 14 '21 at 02:07