java.lang.IndexOutOfBoundsException: 1 | Scala - list

I have this code:
class myFunc{
def summatory(list: List[Int]): Int= list match{
case Nil => 0
case _ => list(1) + summatory(list.tail)
}
}
But I'm getting this error:
"scalac -classpath . -d . main.scala
scala -classpath . Main
java.lang.IndexOutOfBoundsException: 1"
How can I solve it?

Collection indexes in Scala a zero-based, so quick fix would be to just use element at 0 index (otherwise your code will fail on the recursive call processing the last element):
case _ => list(0) + summatory(list.tail)
But better just use pattern matching:
def summatory(list: List[Int]): Int = list match {
case x :: xs => x + summatory(xs)
case Nil => 0
}
Or in particular case of sum - just use sum:
def summatory(list: List[Int]): Int = list.sum

Related

how to get this result list result = List(1,2,3,4,5,6,7) from val l1 = List(1,2,List(3,List(4,5,6),5,6,7) in scala? [duplicate]

This question already has answers here:
Scala flatten a List
(5 answers)
Closed 4 months ago.
how to achieve below result list from the list val l1 = List(1,2,List(3,List(4,5,6),5,6,7)?
result = List(1,2,3,4,5,6,7)
Strangely enough, this actually works in Scala 3, and is kinda-sorta "type-safe":
type NestedList[A] = A match {
case Int => Int | List[NestedList[Int]]
case _ => A | List[NestedList[A]]
}
val input: NestedList[Int] = List(1,2,List(3,List(4,5,6),5,6,7))
def flattenNested[A](nested: NestedList[A]): List[A] =
nested match
case xs: List[NestedList[A]] => xs.flatMap(flattenNested)
case x: A => List(x)
val result: List[Int] = flattenNested(input)
println(result.distinct)
I'd consider this more of a curiosity, though, it feels quite buggy. See also discussion here. As it is now, it would be much preferable to model the input data properly as an enum, so one doesn't end up with a mix of Ints and Lists in the first place.
The following would work,
def flattenOps(l1: List[Any]): List[Int] = l1 match {
case head :: tail => head match {
case ls: List[_] => flattenOps(ls) ::: flattenOps(tail)
case i: Int => i :: flattenOps(tail)
}
case Nil => Nil
}
flattenOps(l1).distinct
Regardless the strange input, I would like to make a common pattern of my items in the list:
import scala.reflec.ClassTag
sealed trait ListItem[A] {
def flattenedItems: List[A]
}
case class SingleItem[A](value: A) extends ListItem[A] {
def flattenedItems: List[A] = value :: Nil
}
case class NestedItems[A](values: List[ListItem[A]]) extends ListItem[A] {
def flattenedItems: List[A] = values.flatMap(_.flattenedItems)
}
// The above would probably take much less lines of code in Scala 3
object ListItem {
def parse[A : ClassTag](value: Any): ListItem[A] = {
value match {
case single: A => SingleItem(single)
case nested: List[Any] => NestedItems(nested.map(parse[A]))
}
}
}
Then given the list as:
val l = List(1, 2, List(3, List(4, 5, 6), 5, 6, 7))
You can parse each value, and then get flattened values using the ListItem's method:
val itemizedList: List[ListItem[Int]] = l.map(ListItem.parse[Int])
val result = itemizedList.flatMap(_.flattenedItems).distinct

Split a list into half by even and odd indexes? TailRecursive + match

Define a tail recursive function:def divide[A](l: List[A]): (List[A], List[A]) that will split the list into two. In the first, there will be elements on even indexes, in the second, there will be elements on odd indexes.
for List (1, 3, 5, 6, 7), the function should return: (List (1, 5, 7), List (3, 6)).
import scala.annotation.tailrec
object Main extends App {
def divide[A](l: List[A]): (List[A], List[A]) = {
#tailrec
def helper(l1: List[A], l2: List[A]) = {
... match {
case
Any help would be great, i dont even know how to start, because i cant simply use x % 2 == 0 with case..
Another option you have, which is not a tailrec, but does not reverse the list, is:
def divide[A](l: List[A]): (List[A], List[A]) = {
def helper(l: List[A]): (List[A], List[A]) = l match {
case Nil => (Nil, Nil)
case head :: Nil => (List(head), Nil)
case even :: odd :: rest =>
val (evenList, oddList) = helper(rest)
(even :: evenList, odd :: oddList)
}
helper(l)
}
Code run at Scastie.
If you'd like to do that in the functional way, you can do:
val (evenWithIndex, oddWithIndex) = List(1, 3, 5, 6, 7).zipWithIndex.partition(_._2 % 2 == 0)
val even = evenWithIndex.map(_._1)
val odd = oddWithIndex.map(_._1)
Maybe you could think of the base case first - A list with one element. In that case, you need to put that in the list of odd indices.
If you have more elements, you need to call the same method, but for the second call, you need to put the element in the list of event indices.
Also, you may notice that, if you have an odd number of elements in the list, you have more numbers in the list of odd indices than that of the even. In case if you have an even number of elements, you have an equal number of elements in both lists.
So you may think of a function like below,
import scala.annotation.tailrec
def divide[A](l: List[A]): (List[A], List[A]) = {
#tailrec
def helper(l: List[A], list1:List[A], list2:List[A]):(List[A], List[A]) = {
l match {
case Nil if list1.size > list2.size => (list1.reverse, list2.reverse) // case 1: odd number of elements
case Nil if list1.size < list2.size => (list2.reverse, list1.reverse) // case 2: odd number of elements
case Nil if list1.size == list2.size => (list1.reverse, list2.reverse) // case 3: even number of elements
case head::tail => helper(tail, list2, head::list1)
}
}
helper(l, List(), List())
}
Now if you see closely, case 1 never occurs as we are swapping the positions of the lists of the odd and even indices. So, we can remove this.
import scala.annotation.tailrec
def divide[A](l: List[A]): (List[A], List[A]) = {
#tailrec
def helper(l: List[A], list1:List[A], list2:List[A]):(List[A], List[A]) = {
l match {
case Nil if list1.size < list2.size => (list2.reverse, list1.reverse) // case 1: odd number of elements
case Nil => (list1.reverse, list2.reverse) // case 2: even number of elements
case head::tail => helper(tail, list2, head::list1)
}
}
helper(l, List(), List())
}
Update
Based on the comment by #Dima, I have removed the extra check from the second case. Also, the code based on the approach he mentioned is,
import scala.annotation.tailrec
def divide[A](l: List[A]): (List[A], List[A]) = {
#tailrec
def helper(l: List[A],
i: Int,
result:(List[A], List[A])):(List[A], List[A]) = l match {
case Nil => (result._1.reverse, result._2.reverse)
case head::tail if i%2 == 0 => helper(tail, (i+1), (head::result._1, result._2))
case head::tail => helper(tail, (i+1), (result._1, head::result._2))
}
helper(l, 0, (List(), List()))
}

Scala flatMap, what are ms and e?

I'm learning Scala and in the below code using flatMap (taken from 99 Scala problems) I have
def myflatten(somelist : List[Any]): List[Any] = somelist flatMap {
case ms: List[_] => flatten(ms)
case e => List(e)
}
Now Im totally confused what the 'ms' and 'e' are? they must be something key as if I change ms to say dd, I get the error "not found value ms". If I hover over them i get a tool-tip saying 'ms' is a 'List[ ][ ]' and 'e' is 'Any'.
I've tried googling for "Scala List elements ms and e" or "Scala flatMap ms and e" or "Scala what do case ms and case e mean?" but I have not seem to find anything that explains what these 'ms' and 'e' are.
Are they keywords? Where can I find info on them in the Scala documentation?
P.S. I understand the code, but just not what ms and e are
If you're new, let me explain step by step whats going on here.
def myflatten(somelist : List[Any]): List[Any] = somelist flatMap {
case ms: List[_] => flatten(ms)
case e => List(e)
}
Written verbosely:
def myflatten(somelist : List[Any]): List[Any] = somelist flatMap { something =>
something match {
case ms: List[_] => flatten(ms)
case e => List(e)
}
}
What is ms and e?
First let me break this down.
You are flatMapping over a List[Any].
val x = List("Str1", "Str2", "Str3")
val y = x flatMap { elementInList => List(elementInList) }
This means for each element in the list, you are creating a new List with that element in it. Because its a flatMap you essentially get the same (same elements) list back.
Checkout what would happen if you use map instead of flatMap:
val x = List("Str1", "Str2", "Str3")
val y = x map { elementInList => List(elementInList) }
the val y would be:
List(List("Str1"), List("Str2"), List("Str3"))
check out http://www.brunton-spall.co.uk/post/2011/12/02/map-map-and-flatmap-in-scala/
now, looking at the verbose example:
def myflatten(somelist : List[Any]): List[Any] = somelist flatMap { something =>
something match {
case ms: List[_] => flatten(ms)
case e => List(e)
}
}
you are matching on the element in the list or in this case called something.
you are also matching on the elements type.
for example
def myMatch(e: Any): String = {
e match {
case x: String => "Its a String: " + x
case y: Int => "Its a Int: " + y
//notice how im using x twice.. its because they're in separate scope!
case x: Boolean => "Its a Boolean: " + x
case _ => "Its something else!"
}
}
invoke myMatch with the param "hello" and it will return "Its a String: hello".
invoke myMatch with the param 1 and it will return "Its a Int: 1".
check out http://docs.scala-lang.org/tutorials/tour/pattern-matching.html
What is e and ms?
lets look at your code:
def myflatten(somelist : List[Any]): List[Any] = somelist flatMap {
case ms: List[_] => flatten(ms)
case e => List(e)
}
If the element in the list which we are currently looking at is of the type List[_] (the same as List[Any]), we then execute this block, flatten(ms).
ms is the val assigned to the element once matched.
If the element in the list which we are currently looking at is of the type _ or essentially default (case _ =>) then return a List(e) containing one element, which is the element which we were looking at.
This would always return a List[List[Any]]. Which is then flattened to a List[Any].
I hope this helps,
Rhys
Here case ms: List[_] is a typed matching for List type elements. ms is not a keyword, it's just a variable representing element of type List.
And case e is a variable matching, it is kind of catch all scenario. It matches for all elements which are not List (as Lists will be matched by the first case). Again e is also not a keyword.
For more info you can read Kinds of patterns
ms, e - it's only variable names. You can call them as you wish.
In first case:
case ms: List[_] => flatten(ms)
you suppose that content of your list
def myflatten(somelist : List[Any])
can be matched as List[_] of any type
In second case statement:
case e => List(e)
you suppose that content of your list can be anything else.
Read official doc: http://docs.scala-lang.org/tutorials/tour/pattern-matching.html
And here some tutorial: https://kerflyn.wordpress.com/2011/02/14/playing-with-scalas-pattern-matching/
to get some background about scala pattern matching.
In general you are comparing with two different cases (ie) case ms having list of any and the other one is of case default specified by e. so if you have list[_] then will implement flat map or else the second option you specified

How to fix the pattern-matching exhaustive warning?

Some scala code:
val list = List(Some("aaa"), Some("bbb"), None, ...)
list.filter(_!=None).map {
case Some(x) => x + "!!!"
// I don't want to handle `None` case since they are not possible
// case None
}
When I run it, the compiler complains:
<console>:9: warning: match may not be exhaustive.
It would fail on the following input: None
list.filter(_!=None).map {
^
res0: List[String] = List(aaa!!!, bbb!!!)
How to fix that warning without providing the case None line?
If you are using map after filter, you may to use collect.
list collect { case Some(x) => x + "!!!" }
you can use flatten
scala> val list = List(Some("aaa"), Some("bbb"), None).flatten
list: List[String] = List(aaa, bbb)
scala> list.map {
| x => x + "!!!"
| }
res1: List[String] = List(aaa!!!, bbb!!!)
You could use the #unchecked annotation, although that requires some additional code:
list.filter(_!=None).map { x => ( x : #unchecked) match {
case Some(x) => x + "!!!"
}
}
You can use get method instead of pattern matching.
Here is example code:
scala> val list = List(Some("aaa"), Some("bbb"), None)
list: List[Option[String]] = List(Some(aaa), Some(bbb), None)
scala> list.filter(_ != None).map(_.get + "!!!")
res0: List[String] = List(aaa!!!, bbb!!!)
some other way to solve this issue, without filter and pattern matching
scala> list.flatten map (_ + "!!!")
or
scala> list.flatMap (_ map (_ + "!!!"))

Pattern matching on a list in Scala

I'm a little confused regarding pattern matching on a list in Scala.
For example.
val simplelist: List[Char] = List('a', 'b', 'c', 'd')
//> simplelist : List[Char] = List(a, b, c, d)
def simple_fun(list: List[Char]) = list match {
case (x:Char) :: (y:List[Char]) => println(x)
case _ => Nil
}
//> simple_fun: (list: List[Char])Any
simple_fun(simplelist)
//> a
//| res0: Any = ()
This currently prints only one line of output. Should it not run/pattern match on each element of the List ?
EDIT: I fixed the compile errors and copied the output from the REPL.
Unless you are repeatedly calling simple_fun in some way, what you have there will pattern match the first element and nothing more. To get it to match the whole list, you can get simple_fun to call itself recursively, like this:
val simplelist: List[Char] = List('a', 'b', 'c', 'd')
def simple_fun(list: List[Char]): List[Nothing] = list match {
case x :: xs => {
println(x)
simple_fun(xs)
}
case _ => Nil
}
Note I've also left out some of the types as the Scala compiler can infer them, leaving you with less cluttered, more readable code.
As a small side-note, calling println repeatedly inside the function like that is not particularly functional - as it is all about side effects. A more idiomatic approach would be to have the function construct a string describing the list, which is then output with a single call to println - so the side-effects are kept in a single well-defined place. Something like this would be one approach:
def simple_fun(list: List[Char]):String = list match {
case x :: xs => x.toString + simple_fun(xs)
case Nil => ""
}
println(simple_fun(simple_list))
I would also like to mention that the case for lists can be divided not only the head and tail, as well as any N number of list elements:
def anyFunction(list: List[Int]): Unit =
list match {
// ...methods that have already been shown
case first :: second :: Nil => println(s"List has only 2 elements: $first and $second")
case first :: second :: tail => println(s"First: $first \nSecond: $second \nTail: $tail")
}
Hope it will be useful to someone.
I think the following should work:
def flatten(l: List[_]): List[Any] = l match {
case Nil => Nil
case (head: List[_]) :: tail => flatten(head) ::: flatten(tail)
case head :: tail => head :: flatten(tail)
}
The first line is a match for Nil, so if we don't find anything return nothing.
The second line will identify List of Lists and recall the flatten method and flatten the list of lists.