Matching over lists in Scala

I know that a map function takes each element of a list (sequence) and applies a function to it. Recursively (and excluding completion conditions, etc.)

map(s, f) = f(s.head) :: map(s.tail, f) 

I am looking for a function that does something like

 foo(s, f) = f(s) :: map(s.tail, f). 

So, "mapper", where the display function is called on the subnet, and not on the individual elements. In lisp terms, I'm looking for a list of maps, not a map. Does something like this exist, or do I need to collapse my own (or use recursion)?

As an alternative, I would take a function that takes as an input sequence and returns a sequence of intermediate subsequences, i.e.

 bar(s, f) = s :: bar(s.tail, f) 
+6
scala functional-programming list-manipulation
source share
3 answers

/ * This approach defines mapList in terms of another useful method called tails. Like Daniel, I will put him in an implicit list extension, but this is purely a matter of taste * /

 implicit def richerList[A](list : List[A]) = new { 

/ * Here, a method called the tail is called that returns every possible tail in the list. This tail is recursive, so it will not explode on large lists. Note that it is slightly different from the Haskell function with the same name. The Haskell version always adds an empty list to the result * /

  def tails : List[List[A]] = { def loop(ls : List[A], accum : List[List[A]]) : List[List[A]] = ls match { case _ :: tail => loop(tail, ls :: accum) case _ => accum } loop(list, Nil).reverse } 

/ * This is what using tails looks like

 scala> "abc".toList.tails res0: List[List[Char]] = List(List(a, b, c), List(b, c), List(c)) 

* /

/ * Now we can define a mapList based on tails * /

  def mapList[B](f : List[A] => B) = tails map f } 

/ * And this is what using mapList looks like

 scala> "abc".toList mapList (_.reverse.mkString) res1: List[String] = List(cba, cb, c) 

* /

+5
source share

You basically determined what you are looking for in the pseudo-code, so it’s easy to add such a method to the Scala list using implicit conversions:

 object ExtendedList{ implicit def List2ExtendedList[A](l:List[A])=new ExtendedList(l) } class ExtendedList[A](l:List[A]){ import ExtendedList._ def mapList[B](f:List[A]=>B):List[B]=l.length match { case 0 => List() case _ => f(l)::l.tail.mapList(f) } } object Test extends Application{ import ExtendedList._ val test = List(5,4,3,2,1) assert(List(15,10,6,3,1)==test.mapList{l=>(0/:l){_+_}}) } 

Is this what you are looking for?

+2
source share

Another answer is close, but you should never use List#length unless absolutely necessary. In particular, he makes his decision O (n ^ 2) when the task is inherently O (n). Here's the cleaned version:

 implicit def addListSyntax[A](list: List[A]) = new { def mapList[B](f: List[A]=>B) = { // use inner function to avoid repeated conversions def loop(list: List[A]): List[B] = list match { case ls @ (_ :: tail) => f(ls) :: loop(tail) case Nil => Nil } loop(list) } } 

And to answer your initial question: no, there is no way to do this using standard utility methods. I'm actually a little curious why you need something like this ...

+1
source share

All Articles