I am trying to find an effective way to do summation of the list up to the selected index.
var groupList : List[Int] = List(1,3,4,5)
What can i do to achieve if i select indexOf(2), it will do summation up to that index? ( 1 + 3 + 4) ?
How about:
val idx = 2
groupList.take(idx+1).sum
// res3: Int = 8
Or for efficiency:
groupList.toIterator.take(idx+1)
// res4: Iterator[Int] = non-empty iterator
groupList.toIterator.take(idx+1).sum
// res5: Int = 8
For example, my input is:
scala> val myList = List("7842", "abf45", "abd", "56")
myList: List[String] = List(7842, abf45, abd, 56)
7842 and 56 can be converted to Int; therefore, my expected output is 2. We can assume that negative integers don't happen, so -67 is not possible.
This is what I have so far:
scala> myList.map(x => Try(x.toInt).getOrElse(-1)).count(_ > -1)
res15: Int = 2
This should work correctly, but I feel like I am missing a more elegant and readable solution, because all I have to do is count number of successes.
I would caution against using exception handling (like Try) in control flow -- it's very slow.
Here's a solution that uses idiomatic Scala collection operations, performs well, and will not count negative numbers:
scala> val myList = List("7842", "abf45", "abd", "56")
myList: List[String] = List(7842, abf45, abd, 56)
scala> myList.count(_.forall(_.isDigit))
res8: Int = 2
EDIT: #immibis pointed out that this won't detect strings of numbers that exceed Integer.MaxValue. If this is a concern, I would recommend one of the following approaches:
import scala.util.Try
myList.count(x => Try(x.toInt).filter(_ >= 0).isSuccess)
or, if you want to keep the performance of my first answer while still handling this edge case:
import scala.util.Try
myList.count(x => x.forall(_.isDigit) && Try(x.toInt).filter(_ >= 0).isSuccess)
This is a bit shorter:
myList.count(x => Try(x.toInt).isSuccess)
Note that this solution will handle any string that can be converted to integer via .toInt, including negative numbers.
You may consider string.matches method with regex as well, to match only positive integers:
val myList = List("7842", "abf45", "abd", "-56")
// myList: List[String] = List(7842, abf45, abd, -56)
myList.count(_.matches("\\d+"))
// res18: Int = 1
If negative integers need to be counted (and take into account possible +/- signs):
myList.count(_.matches("[+-]?\\d+"))
// res17: Int = 2
Starting Scala 2.13 and the introduction of String::toIntOption, we can count items ("34"/"2s3") for which applying toIntOption (Some(34)/None) is defined (true/false):
List("34", "abf45", "2s3", "56").count(_.toIntOption.isDefined) // 2
When I created a Scala Array and added one element, but the array length is still 0, and I can not got the added element although I can see it in the construction function.
scala> val arr = Array[String]()
arr: Array[String] = Array()
scala> arr:+"adf"
res9: Array[String] = Array(adf)
scala> println(arr(0))
java.lang.ArrayIndexOutOfBoundsException: 0
... 33 elided
You declared Array of 0 size. It cannot have any elements. Your array is of size 0. Array[String]() is a array contructor syntax.
:+ creates a new Array with with the given element so the old array is empty even after doing the :+ operation.
You have to use ofDim function to declare the array first of certain size and then you can put elements inside using arr(index) = value syntax.
Once declared array size do not increase dynamically like list. Trying to append values would create new array instance.
or you can initialize the array during creation itself using the Array("apple", "ball") syntax.
val size = 1
val arr = Array.ofDim[String](size)
arr(0) = "apple"
Scala REPL
scala> val size = 1
size: Int = 1
scala> val arr = Array.ofDim[String](size)
arr: Array[String] = Array(null)
scala> arr(0) = "apple"
scala> arr(0)
res12: String = apple
This Stackoverflow post discusses the potential problem of a numeric overflow if not appending L to a number:
Here's an example from the REPL:
scala> 100000 * 100000 // no type specified, so numbers are `int`'s
res0: Int = 1410065408
One way to avoid this problem is to use L.
scala> 100000L * 100000L
res1: Long = 10000000000
Or to specify the number's types:
scala> val x: Long = 100000
x: Long = 100000
scala> x * x
res2: Long = 10000000000
What's considered the best practice to properly specify a number's type?
You should always use L if you are using a long. Otherwise, you can still have problems:
scala> val x: Long = 10000000000
<console>:1: error: integer number too large
val x: Long = 10000000000
^
scala> val x = 10000000000L
x: Long = 10000000000
The conversion due to type ascription happens after the literal has been interpreted as Int.
I ran into some issues today making assignments to a var field in a case class instance stored in a map. Here's a simple session in the repl demonstrating the problem:
scala> case class X(var x: Int)
defined class X
scala> val m = Map('x -> X(1))
m: scala.collection.immutable.Map[Symbol,X] = Map('x -> X(1))
scala> m
res0: scala.collection.immutable.Map[Symbol,X] = Map('x -> X(1))
scala> m('x).x = 7
scala> m
res1: scala.collection.immutable.Map[Symbol,X] = Map('x -> X(1))
scala> val x = m('x)
x: X = X(1)
scala> x.x = 7
x.x: Int = 7
scala> x
res2: X = X(7)
scala> m
res3: scala.collection.immutable.Map[Symbol,X] = Map('x -> X(7))
scala> m('x).x_=(8)
scala> m
res5: scala.collection.immutable.Map[Symbol,X] = Map('x -> X(8))
The first attempt at assignment does nothing. However, storing the instance in a val and then doing the assignment works, as does directly calling the assignment method for the field.
I'm using Scala 2.9.2.
If this is expected behavior, it would be nice if someone could explain it to me because I can't seem to make sense of it right now. If this is a bug then that would be good to know as well.
Either way, it would also be interesting to know where that first m('x).x = 7 assignment is going. I assume something is getting mutated somewhere—I just have no idea what that something could be.
Update: It looks like this only happens in the repl. I just tried compiling the code and the assignment happens as expected. So, what is the repl doing to my assignment?
This seems to be a bug. If one executes this with a 2.10 nightly an error message is thrown:
scala> m('x).x = 7
<console>:10: error: ')' expected but string literal found.
+ "m(scala.Symbol("x")).x: Int = " + `$ires0` + "\n"
^
I created a ticket for this.