Functional way to loop over nested list - scala

I was given a question to compare two trees. Something like below:
case class Node(elem:String, child:List[Node])
In order to compare each elements of the trees, I have following functions:
def compare(n1:Node, n2:Node): Boolean {
if(n1.elem == n2.elem){
return compare(n1.child, n2.child)
}
}
def compare(c1:List[Node], c2:List[Node]): Boolean {
while (c1.notEmpty) {
//filter, map etc call function above to compare the element recursively
}
}
Basically algorithm is for each elements in n1, we are checking for a match in n2. I was told that this is very imperative way and not functional way. What would be a functional way to achieve this behaviour. In other words, how do we remove while loop when comparing the list of children?

Consider zipping both lists and using forall which holds true only if each and every predicate it processes evaluates to true; for instance like this,
def compare(c1: List[Node], c2: List[Node]): Boolean =
(c1.sorted zip c2.sorted).forall(c => compare(c._1,c._2))
Note that forall will halt the evaluations as it encounters the first false. Cases of unequal length lists of nodes may be tackled with zipAll by defining an EmptyNode class for padding length differences; also both lists empty may compare to true.
Update
Sorted lists of nodes for soundness following comment by #JohnB.

If I understood your question correctly, you want to compare every element of the first list with every element of the second list. The following code achieves this. It gets rid of the while loop via a tail-recursion.
import scala.annotation.tailrec
def cmp(a:Int, b:Int) = a > b
#tailrec
def compare(xs: List[Int], ys: List[Int]): Boolean = xs match {
case Nil => true
case head :: tail if ys.forall(x => cmp(head, x)) => compare(tail, ys)
case _ => false
}

Related

Scala: Find and update one element in a list

I am trying to find an elegant way to do:
val l = List(1,2,3)
val (item, idx) = l.zipWithIndex.find(predicate)
val updatedItem = updating(item)
l.update(idx, updatedItem)
Can I do all in one operation ? Find the item, if it exist replace with updated value and keep it in place.
I could do:
l.map{ i =>
if (predicate(i)) {
updating(i)
} else {
i
}
}
but that's pretty ugly.
The other complexity is the fact that I want to update only the first element which match predicate .
Edit: Attempt:
implicit class UpdateList[A](l: List[A]) {
def filterMap(p: A => Boolean)(update: A => A): List[A] = {
l.map(a => if (p(a)) update(a) else a)
}
def updateFirst(p: A => Boolean)(update: A => A): List[A] = {
val found = l.zipWithIndex.find { case (item, _) => p(item) }
found match {
case Some((item, idx)) => l.updated(idx, update(item))
case None => l
}
}
}
I don't know any way to make this in one pass of the collection without using a mutable variable. With two passes you can do it using foldLeft as in:
def updateFirst[A](list:List[A])(predicate:A => Boolean, newValue:A):List[A] = {
list.foldLeft((List.empty[A], predicate))((acc, it) => {acc match {
case (nl,pr) => if (pr(it)) (newValue::nl, _ => false) else (it::nl, pr)
}})._1.reverse
}
The idea is that foldLeft allows passing additional data through iteration. In this particular implementation I change the predicate to the fixed one that always returns false. Unfortunately you can't build a List from the head in an efficient way so this requires another pass for reverse.
I believe it is obvious how to do it using a combination of map and var
Note: performance of the List.map is the same as of a single pass over the list only because internally the standard library is mutable. Particularly the cons class :: is declared as
final case class ::[B](override val head: B, private[scala] var tl: List[B]) extends List[B] {
so tl is actually a var and this is exploited by the map implementation to build a list from the head in an efficient way. The field is private[scala] so you can't use the same trick from outside of the standard library. Unfortunately I don't see any other API call that allows to use this feature to reduce the complexity of your problem to a single pass.
You can avoid .zipWithIndex() by using .indexWhere().
To improve complexity, use Vector so that l(idx) becomes effectively constant time.
val l = Vector(1,2,3)
val idx = l.indexWhere(predicate)
val updatedItem = updating(l(idx))
l.updated(idx, updatedItem)
Reason for using scala.collection.immutable.Vector rather than List:
Scala's List is a linked list, which means data are access in O(n) time. Scala's Vector is indexed, meaning data can be read from any point in effectively constant time.
You may also consider mutable collections if you're modifying just one element in a very large collection.
https://docs.scala-lang.org/overviews/collections/performance-characteristics.html

How to create scala recursive method

I am trying to help a recursive method in scala that removes a particular number from a list and returns that list without the given number.
I can only use if/else statements and pairing (::)
So far I have this but I am not sure how to remove items from a list in scala.
def removeNum(lst: List[Int]): lst2:List[Int] = lst match {
var lst2:Int
case Nil =>0
case h::t=>{
if(h !=0)
lst2(h)// how do I iterate thru the list without using foreach?
}
else {
removeNum(rest)
}
}
I'm looking for a better approach to this method.
The basic approach is to compare the "given number" against the head of the list. If there is a match, return the recursive result on only the rest of the list. Otherwise, return a list created by keeping the head of the list and recursing on the rest of the list. Notice that it is easier to think about whether or not to keep the head of the list rather than thinking about removing elements from the list.
Note that this requires a second parameter: the "given number" which you want to remove.
While I think you should use filter, you could use:
def removeNum(xs: List[Int], toRemove: Int): List[Int] = xs match {
case x :: xss => if (x == toRemove)
removeNum(xss, toRemove)
else
x :: removeNum(xss, toRemove)
case List() => List()
}

What is meant by not generating the answer lazily in this code?

I came across the following code:
/*
Unlike `take`, `drop` is not incremental. That is, it doesn't generate the
answer lazily. It must traverse the first `n` elements of the stream eagerly.
*/
#annotation.tailrec
final def drop(n: Int): Stream[A] = this match {
case Cons(_, t) if n > 0 => t().drop(n - 1)
case _ => this
}
/*
`take` first checks if n==0. In that case we need not look at the stream at all.
*/
def take(n: Int): Stream[A] = this match {
case Cons(h, t) if n > 1 => cons(h(), t().take(n - 1))
case Cons(h, _) if n == 1 => cons(h(), empty)
case _ => empty
}
Could someone explain what is meant by the comment:
Unlike take, drop is not incremental. That is, it doesn't generate the
answer lazily. It must traverse the first n elements of the stream eagerly.
To me, it looks like both the drop and take functions have to traverse the first n elements of the stream eagerly? What is it about the drop function that causes the first n elements to be eagerly traversed?
(Full code context here: https://github.com/fpinscala/fpinscala/blob/master/answers/src/main/scala/fpinscala/laziness/Stream.scala)
The definition for Cons is:
case class Cons[+A](h: () => A, t: () => Stream[A]) extends Stream[A]
Notice that the second parameter, t, takes a function (from Unit to Stream[A]), not the evaluation of that function. This is not evaluated until required, and hence is lazy, as is the take method that calls it.
Compare this to drop which calls t() itself rather than passing it into the Cons, forcing the immediate evaluation.
The key point is that cons is lazy. That is if the recursion is inside of cons, the recursion won't happen until the tail of the generated list is actually accessed. Whereas if the recursion is outside, it happens right away.
So drop is eager because the recursion is not inside a cons (or any other lazy construct).

How to return multiple random elements from List scala

How can I return multiple random elements from a List .
This question How to choose a random element from an array in Scala? refers to using :
import scala.util.Random
val A = Array("please", "help", "me")
Random.shuffle(A.toList).head
The mutable in me is thinking I could create a for loop and keep selecting the next random element (excluding the one already selected) and add that to a new List. Is there a more idiomatic/functional way to achieve this in Scala ?
The head method will return the first element of the list, but take(n) will return up to n elements from the front of the list. So after you shuffle the list, just use take:
def takeRandomN[A](n: Int, as: List[A]) =
scala.util.Random.shuffle(as).take(n)
If your list as is shorter than n then this will simply shuffle as.
It might seem like this is going to be slow for large lists that you only want a small subset from, but a random subset will be likely be uniformly sampled from the list, so you'll have to traverse the whole thing anyway. For an Array or other structure with random access, you can do better, but for List you cannot.
More "conservative" variant without using mutables/vars. Just for the sake of exercise:
def takeRandomFrom[T](n: Int, list: List[T]): List[T] = {
#tailrec
def innerTake(n:Int, list: List[T], result: List[T]): List[T] = {
if (n == 0 || list.isEmpty) {
result
} else {
innerTake(n - 1, list.tail, list.head :: result)
}
}
innerTake(n, Random.shuffle(list), Nil)
}
takeRandomFrom(2, Array("please", "help", "me").toList)

Mapping many Eithers to one Either with many

Say I have a monadic function in called processOne defined like this:
def processOne(input: Input): Either[ErrorType, Output] = ...
Given a list of "Inputs", I would like to return a corresponding list of "Outputs" wrapped in an Either:
def processMany(inputs: Seq[Input]): Either[ErrorType, Seq[Output]] = ...
processMany will call processOne for each input it has, however, I would like it to terminate the first time (if any) that processOne returns a Left, and return that Left, otherwise return a Right with a list of the outputs.
My question: what is the best way to implement processMany? Is it possible to accomplish this behavior using a for expression, or is it going to be necessary for me to iterate the list myself recursively?
With Scalaz 7:
def processMany(inputs: Seq[Input]): Either[ErrorType, Seq[Output]] =
inputs.toStream traverseU processOne
Converting inputs to a Stream[Input] takes advantage of the non-strict traverse implementation for Stream, i.e. gives you the short-circuiting behaviour you want.
By the way, you tagged this "monads", but traversal requires only an applicative functor (which, as it happens, is probably defined in terms of the monad for Either). For further reference, see the paper The Essence of the Iterator Pattern, or, for a Scala-based interpretation, Eric Torreborre's blog post on the subject.
The easiest with standard Scala, which doesn't evaluate more than is necessary, would probably be
def processMany(inputs: Seq[Input]): Either[ErrorType, Seq[Output]] = {
Right(inputs.map{ x =>
processOne(x) match {
case Right(r) => r
case Left(l) => return Left(l)
}
})
}
A fold would be more compact, but wouldn't short-circuit when it hit a left (it'd just keep carrying it along while you iterated through the entire input).
For now, I've decided to just solve this using recursion, as I am reluctant to add a dependency to a library (Scalaz).
(Types and names in my application have been changed here in order to appear more generic)
def processMany(inputs: Seq[Input]): Either[ErrorType, Seq[Output]] = {
import scala.annotation.tailrec
#tailrec
def traverse(acc: Vector[Output], inputs: List[Input]): Either[ErrorType, Seq[Output]] = {
inputs match {
case Nil => Right(acc)
case input :: more =>
processOne(input) match {
case Right(output) => traverse(acc :+ output, more)
case Left(e) => Left(e)
}
}
}
traverse(Vector[Output](), inputs.toList)
}