====== Lecture 6. List applications ====== /* Topic 1. Liste (din Scala). */ val l = List(1,2,3) //Cons(1,Cons(2,Cons(3,Void))) 1 :: 2 :: 3 :: Nil List(1,2,3) match { case Nil => 0 case x :: y :: Nil => 2 case x :: y :: _ => 3 case x :: xs => 1 } // listele sunt orientate obiect l.head // 1 l.tail // l.map(_*2) // transformare per element l.foldRight(0)(_ + _) // 1 + (2 + (3 + acc))) l.foldLeft(Nil:List[Int])((acc,x) => x :: acc) // (acc op 1) op 2) op 3 val lp = List((1,2), (3,1), (4,4)) lp.sortBy(_._2) lp.sortBy(x => x._1 + x._2) /* notatia infix*/ trait Nat { def +(other: Nat): Nat def -(other: Nat): Nat } case object Zero extends Nat { override def +(other: Nat): Nat = other override def -(other: Nat): Nat = Zero } case class Succ(n: Nat) extends Nat { override def +(other: Nat): Nat = Succ(n + other) override def -(other: Nat): Nat = other match { case Zero => this case Succ(np) => n - np } } val x = Succ(Zero) val y = Succ(Succ(Zero)) x + y /* In Scala, expresia: token1 token2 token3 se citeste: token1.token2(token3), cu conditia ca: token1 sa fie un obiect token2 sa fie o functie membru a clasei obiectului resp. token3 sa fie un parametru */ x.-(y) x - y List(1,2,3) map (_+1) List(1,2,3).map(_+1) val f = ((x: Int) => x + 1) andThen (_*2) andThen (_-1) f(1) val emails = List("matei@gmail.com", "mihai@gmail.com", "ana@gmail.com", "john@yahoo.com", "mary@aol.com", "maria@upb.ro") /* vrem sa aflam frecventa cu care apare un domeniu in lista de mai sus */ /* sa zicem ca ne intereseaza frecventa pt domeniul gmail */ // Cum implementam (abordam) aceasta problema FUNCTIONAL? "Test".toList /* This function will be included later in the final implementation: def getDomain(email: List[Char]): List[Char] = email match { case '@' :: xs => xs case _ :: xs => getDomain(xs) } getDomain("Matei@gmail.com".toList) */ type Str = List[Char] def getFrequencies(emails: List[String]): List[(String,Int)] = { def getDomain(email: Str): Str = email match { case '@' :: xs => xs case _ :: xs => getDomain(xs) } def join(domain: Str): String = domain.foldRight("")(_ + _) // introducerea unui caracter intr-un string /* recursive variant for groupLists. We prefer writing is using foldRight, as below: def groupLists(l: List[String]): List[List[String]] = l match { case Nil => Nil case x :: xs => { val r = groupLists(xs) if (x == r.head.head) (x :: r.head) :: r.tail else (x :: Nil) :: r } }*/ def groupLists(l: List[String]): List[List[String]] = l.foldRight(Nil:List[List[String]])((domain,acc) => if (acc == Nil) List(domain)::Nil else if (domain == acc.head.head) (domain :: acc.head) :: acc.tail else (domain :: Nil) :: acc ) // the outer set of parentheses are mandatory, in order to express where does the andThen sequence end val sequence = (((l: List[String]) => l.map(_.toList)) // make each String into a Str (List[Char]) andThen (_.map(getDomain(_))) // extract the domain from each Str andThen (_.map(join(_))) // convert to String back again andThen (_.sortBy(x => x)) // sort the list of domains andThen (groupLists(_)) // group identical domains andThen (_.map(group => (group.head,group.size)))) // transform each group into a frequency pair sequence(emails) } getFrequencies(emails) /* def groupLists(l: List[String]): List[List[String]] = l match { case x :: Nil => List(x) :: Nil case x :: xs => { val r = groupLists(xs) if (x == r.head.head) (x :: r.head) :: r.tail else (x :: Nil) :: r } } */