Update the values of a list with their absolute values

2.6k views Asked by At

Newbie to scala.

I am trying to make this code to work for a few hours now . It is intended to update the List[Int](list of integers) with absolute values of the integers. Took a long time to figure out that List is immutable, so found that ListBuffer can be the saviour, but eventually in returning it back into the List form is seeing some issue i guess.

def f (arr:List[Int]) : List[Int] =
{
  val list = new scala.collection.mutable.ListBuffer[Int]();
  val len = arr.length;
  for ( i <- 0 to len)
  {
    if(arr(i) < 0)
    {

      list.append((-1)*arr(i)) ;
    }
    else
    {
      list.append(arr(i));
    }
  }

  return list.toList;

}

which is giving this error:

java.lang.IndexOutOfBoundsException: 12
at scala.collection.LinearSeqOptimized$class.apply(LinearSeqOptimized.scala:52)
at scala.collection.immutable.List.apply(List.scala:84)
at Solution$.f(Solution.scala:7)
at Solution$delayedInit$body.apply(Solution.scala:23)
at scala.Function0$class.apply$mcV$sp(Function0.scala:40)
at scala.runtime.AbstractFunction0.apply$mcV$sp(AbstractFunction0.scala:12)
at scala.App$$anonfun$main$1.apply(App.scala:71)
at scala.App$$anonfun$main$1.apply(App.scala:7...

Not getting what's wrong here.

6

There are 6 answers

4
yǝsʞǝla On BEST ANSWER

The best way is to use Scala functions like @senia suggested in comments. For example:

val res = list map math.abs

But if you want to fix your code just replace to with until. You are getting off by one error:

def f (arr:List[Int]) : List[Int] =
{
val list = new scala.collection.mutable.ListBuffer[Int]();
val len = arr.length;
for ( i <- 0 until len)
{
    if(arr(i) < 0)
    {

        list.append((-1)*arr(i)) ;
    }
    else
    {
        list.append(arr(i));
    }
}

return list.toList;

}

Here is the difference between until and to:

1 to 3
// Range(1, 2, 3)

1 until 3
// Range(1, 2)

You can also remove return, ; and even braces { used with if/else.

0
Joe Stogner On
def f (arr: List[Int]) : List[Int] = {
 arr.map {
     case i if 0 > i => i * -1
     case i => i
 }
}
1
elm On

Yet another version using a for comprehension that avoids indexing,

def f (arr:List[Int]) : List[Int] =
{
  val list = new scala.collection.mutable.ListBuffer[Int]();

  for {
    a <- arr
    sign = if (a < 0) -1 else 1
  } list.append(sign * a)

  return list.toList;
}

As mentioned above, the return may be omitted.

0
fixxer On

Looks like you were trying to solve the challenge from here. Probably you may want to use more functional approach with recursion and immutable List.

def f(arr: List[Int]): List[Int] = arr match {
  case Nil => Nil
  case x :: rest => java.lang.Math.abs(x) :: f(rest)
}
0
Explorer On

You can try using case statements for more neat syntax :

def f(arr:List[Int]):List[Int] = {
val list = scala.collection.mutable.ListBuffer[Int]()
arr.foreach{
    x =>
        x match {
        case _ if (x <0) => list+= (x*(-1))
        case _ => list +=x
    }
}
list.toList
}
1
Iliass On

Beginner friendly: this is how I wrote it

def f(arr: List[Int]) : List[Int] = {
var list = new scala.collection.mutable.ArrayBuffer[Int]();
// var len = arr.length;

for(i <-0 until arr.length) {
    list.append( math.abs(arr(i)));
}

return list.toList; }

I haven't done any time complexity analysis but it's the most straightforward for beginners to understand. Also, it passes all the tests on hackerrank