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

2
  • 8
    This is from "Scala for the impatient". Exercise 3.2 Commented Apr 5, 2013 at 10:12
  • Next time, please mention that it's a homework exercise. Commented Jul 20, 2018 at 9:05

9 Answers 9

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
Sign up to request clarification or add additional context in comments.

2 Comments

I like the use of reverse. Nice.
The exercise says do a loop, then do a for/yield, not a functional solution. Nice though...
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)

4 Comments

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, The for/yield construction makes things nicer a lot of the time, but this isn't a great match for it.
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)
Sory, there are both task: with swap elements with existing array and while creating new one (with map-function)
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.

2 Comments

Nice. This seems to be more in the spirit of the exercise.
Good answer for the question asked.
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)
    )
}

Comments

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

Comments

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) }

Comments

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

Comments

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
  }

Comments

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)
}

3 Comments

@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.
.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 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

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.