Friday, October 30, 2009
Groupby - collection processing
Iterator and Iterable have most of the most useful methods when dealing with collections. Fold, Map, Filter are probably the most common. But other very useful methods include grouped/groupBy, sliding, find, forall, foreach, and many more. I want to cover Iterable's groupBy method in this topic.
This is a Scala 2.8 and later method. It is similar to partition in that it allows the collection to be divided (or partitioned). Partition takes a method with returns a boolean and partitions the collection into two depending on a result. GroupBy takes a function that returns an object and returns a Map with the key being the return value. This allows an arbitrary number of partitions to be made from the collection.
Here is the method signature:
A bit of context is require to understand the three Type parameters A, K and This. This method is defined in a super class of collections called TraversableLike (I will briefly discuss this in the next topic.) TraversableLike takes two type parameters: the type of the collection and the type contained in the collection. Therefore in this method definition, 'This' refers to the collection type (List for example) and A refers to contained type (perhaps Int). Finally K refers to the type returned by the function and are the keys of the groups formed by the method.
Examples:
This is a Scala 2.8 and later method. It is similar to partition in that it allows the collection to be divided (or partitioned). Partition takes a method with returns a boolean and partitions the collection into two depending on a result. GroupBy takes a function that returns an object and returns a Map with the key being the return value. This allows an arbitrary number of partitions to be made from the collection.
Here is the method signature:
- def groupBy[K](f : (A) => K) : Map[K, This]
A bit of context is require to understand the three Type parameters A, K and This. This method is defined in a super class of collections called TraversableLike (I will briefly discuss this in the next topic.) TraversableLike takes two type parameters: the type of the collection and the type contained in the collection. Therefore in this method definition, 'This' refers to the collection type (List for example) and A refers to contained type (perhaps Int). Finally K refers to the type returned by the function and are the keys of the groups formed by the method.
Examples:
- scala> val groups = (1 to 20).toList groupBy {
- | case i if(i<5) => "g1"
- | case i if(i<10) => "g2"
- | case i if(i<15) => "g3"
- | case _ => "g4"
- | }
- res4: scala.collection.Map[java.lang.String,List[Int]] = Map(g1 -> List(1, 2, 3, 4), g2 -> List(5, 6, 7, 8, 9), g3 -> List(10, 11, 12, 13, 14), g4 -> List(15, 16, 17, 18, 19, 20))
- scala> groups.keySet
- res6: scala.collection.Set[java.lang.String] = Set(g1, g2, g3, g4)
- scala> groups("g1")
- res7: List[Int] = List(1, 2, 3, 4)
- scala> val mods = (1 to 20).toList groupBy ( _ % 4 )
- mods: scala.collection.Map[Int,List[Int]] = Map(1 -> List(1, 5, 9, 13, 17), 2 -> List(2, 6, 10, 14, 18), 3 -> List(3, 7,
- 11, 15, 19), 0 -> List(4, 8, 12, 16, 20))
- scala> mods.keySet
- res9: scala.collection.Set[Int] = Set(1, 2, 3, 0)
- scala> mods(1)
- res11: List[Int] = List(1, 5, 9, 13, 17)
Labels:
beginner,
collections,
groupby,
Scala
Thursday, October 29, 2009
Boolean Extractors
As discussed in other topics there are several ways to create custom extractors for objects. See
There is one more custom extractor that can be defined. Simple boolean extractors. They are used as follows:
A boolean extractor is an object that returns Boolean from the unapply method rather than Option[_].
Examples:
There is one more custom extractor that can be defined. Simple boolean extractors. They are used as follows:
- scala> "hello world" match {
- | case HasVowels() => println("Vowel found")
- | case _ => println("No Vowels")
- | }
- Vowel found
A boolean extractor is an object that returns Boolean from the unapply method rather than Option[_].
Examples:
- scala> object HasVowels{ def unapply(in:String):Boolean = in.exists( "aeiou" contains _ ) }
- defined module HasVowels
- // Note that HasVowels() has ().
- // This is critical because otherwise the match checks whether
- // the input is the HasVowels object.
- // The () forces the unapply method to be used for matching
- scala> "hello world" match {
- | case HasVowels() => println("Vowel found")
- | case _ => println("No Vowels")
- | }
- Vowel found
- // Don't forget the ()
- scala> "kkkkkk" match {
- | case HasVowels() => println("Vowel found")
- | case _ => println("No Vowels")
- | }
- No Vowels
- scala> class HasChar(c:Char) {
- | def unapply(in:String) = in.contains(c)
- | }
- defined class HasChar
- scala> val HasC = new HasChar('c')
- HasC: HasChar = HasChar@3f2f529b
- // Don't forget the () it is required here as well
- scala> "It actually works!" match {
- | case HasC() => println("a c was found")
- | case _ => println("no c found")
- | }
- a c was found
- // Don't forget the ()
- scala> "hello world" match {
- | case HasC() => println("a c was found")
- | case _ => println("no c found")
- | }
- no c found
Wednesday, October 28, 2009
Extractors 3 (Operator Style Matching)
One of the blessings and curses of Scala the several rules for creating expressive code (curse because it can be used for evil.) One such rule is related to extractors that allows the following style of match pattern:
The rule is very simple. An extractor object that returns Option[Tuple2[_,_]] (or equivalently Option[(_,_)]) can be expressed in this form.
In other words:
Example to extract out the vowels from a string:
Example for Matching the last element in a list. Thanks to 3-things-you-didnt-know-scala-pattern.html:
- List(1,2,3) match {
- case 1 :: _ => println("found a list that starts with a 1")
- case _ => println("boo")
- }
The rule is very simple. An extractor object that returns Option[Tuple2[_,_]] (or equivalently Option[(_,_)]) can be expressed in this form.
In other words:
object X {def unapply(in:String):Option[(String,String)] = ...}
can be used in a case statement like: case first X head => ...
or case "a" X head => ...
.Example to extract out the vowels from a string:
- scala> object X { def unapply(in:String):Option[(RichString,RichString)] = Some(in.partition( "aeiou" contains _ )) }
- defined module X
- scala> "hello world" match { case head X tail => println(head, tail) }
- (eoo,hll wrld)
- // This is equivalent but a different way of expressing it
- scala> "hello world" match { case X(head, tail) => println(head, tail) }
- (eoo,hll wrld)
Example for Matching the last element in a list. Thanks to 3-things-you-didnt-know-scala-pattern.html:
- scala> object ::> {def unapply[A] (l: List[A]) = Some( (l.init, l.last) )}
- defined module $colon$colon$greater
- scala> List(1, 2, 3) match {
- | case _ ::> last => println(last)
- | }
- 3
- scala> (1 to 9).toList match {
- | case List(1, 2, 3, 4, 5, 6, 7, 8) ::> 9 => "woah!"
- | }
- res12: java.lang.String = woah!
- scala> (1 to 9).toList match {
- | case List(1, 2, 3, 4, 5, 6, 7) ::> 8 ::> 9 => "w00t!"
- | }
- res13: java.lang.String = w00t!
Thursday, October 1, 2009
Vacation
For the next three weeks (Oct 3,2009 to Oct 25) I am going on vacation which means my Internet access will not be regular so I will post when I can but I cannot guarantee any real schedule. So to keep you interested I recommend looking at this very nice overview of Scala's features:
Another Scala Tour
I really liked the presentation on this site.
Jesse
Another Scala Tour
I really liked the presentation on this site.
Jesse
Strings
This topic simply shows several things that can be done with strings. It is not exhaustive and focusses of things that cannot as easily be done with java strings.
Note: Because I am using Scala 2.7 we often need to use mkString to convert the processed string from a sequence of characters to a string. In scala 2.8 this is not required.
Note: Because I am using Scala 2.7 we often need to use mkString to convert the processed string from a sequence of characters to a string. In scala 2.8 this is not required.
- /*
- Making use of raw strings to create a multi line string
- I add a | at the beginning of each line so that we can line up the quote nicely
- in source code then later strip it from the string using stripMargin
- */
- scala> val quote = """|I don-t consider myself a pessimist.
- | |I think of a pessimist as someone who is waiting for it to rain.
- | |And I feel soaked to the skin.
- |
- | |Leonard Cohen"""
- quote: java.lang.String =
- |I don-t consider myself a pessimist.
- |I think of a pessimist as someone who is waiting for it to rain.
- |And I feel soaked to the skin.
-
- |Leonard Cohen
- // capilize the first character of each line
- scala> val capitalized = quote.lines.
- | map( _.trim.capitalize).mkString("\n")
- capitalized: String =
- |I don-t consider myself a pessimist.
- |I think of a pessimist as someone who is waiting for it to rain.
- |And I feel soaked to the skin.
- |Leonard Cohen
- // remove the margin of each line
- scala> quote.stripMargin
- res1: String =
- I don-t consider myself a pessimist.
- I think of a pessimist as someone who is waiting for it to rain.
- And I feel soaked to the skin.
-
- Leonard Cohen
- // this is silly. I reverse the order of each word but keep the words in order
- scala> quote.stripMargin.
- | lines.
- | map( _.split(" ").
- | map(_.reverse).
- | mkString (" ")).
- | mkString("\n")
- res16: String =
- I t-nod redisnoc flesym a .tsimissep
- I kniht fo a tsimissep sa enoemos ohw si gnitiaw rof ti ot .niar
- dnA I leef dekaos ot eht .niks
- dranoeL nehoC
- scala> val myPatch = "-->This is my patch<--"
- myPatch: java.lang.String = -->This is my patch<--
- // I replace the characters from point 10 in the string to myPatch.length
- // (the full patch string)
- scala> quote.patch(10, myPatch, myPatch.length).mkString
- res21: String =
- |I don-t c-->This is my patch<--mist.
- |I think of a pessimist as someone who is waiting for it to rain.
- |And I feel soaked to the skin.
-
- |Leonard Cohen
- // drop the first 3 lines of the string.
- // there is also a take method
- scala> quote.lines.drop(3).mkString("\n").stripMargin
- res25: String =
-
- Leonard Cohen
- // a bunch of examples of converting strings
- scala> "1024".toInt
- res26: Int = 1024
- scala> "1024".toFloat
- res27: Float = 1024.0
- scala> "1024".toDouble
- res28: Double = 1024.0
- scala> "1024".toLong
- res29: Long = 1024
- scala> "102".toByte
- res31: Byte = 102
- scala> "true".toBoolean
- res32: Boolean = true
- // format uses the java.util.Formatter class to format a string
- scala> "Hello %s,\nThe date is %2$tm %2$te,%2$tY".format("Jesse", new java.util.Date())
- res35: String =
- Hello Jesse,
- The date is 09 30,2009
- /*
- More silliness
- I am replacing every other character with the character of the reversed string
-
- this is done by
- 1. convert string to a list and zip it together with its reverse
- We may still need to cover zipping. It basically matches up the
- corresponding elements of two lists into one list
- so 1,2,3 and one,two,three zipped would be (1,one),(2,two),(3,three)
- 2. Add an index to each element in the list with zipWithIndex
- 3. Use map to check if the element is an odd element using the index and return either the original element or the reversed element
-
- Not useful but interesting use of functional idioms
- */
- scala> quote.toList.
- | zip(quote.reverse.toList).
- | zipWithIndex.
- | map {
- | case ((original,reversed),index) if(index % 2 == 0) => original
- | case ((original,reversed),index) => reversed
- | }.
- | mkString
- res42: String = |e oo -r noes|d r m s l e s m s . . i s e t o e|a shlne f anp|s i i t a o e n h .siwrioi gifrrfig ioirwis. h n e o a t i i s|pna f enlhs a|e o t e s i . . s m s e l s m r d|seon r- oo e|
- // filter out all non-vowels
- scala> quote.filter( "aeiou" contains _ ).mkString
- res51: String = ooieeaeiiioaeiiaoeoeoiaiioioaieeoaeoeieoaoe
Labels:
beginner,
raw strings,
Scala,
String
Multiple type bounds on a generic parameter
Suppose you want to declare a method to take objects that implement two interfaces or parent objects. For example suppose the parameter must implement both Iterable and a function so that you can access the elements of the iterable via
This topic is derived from How do I setup multiple type bounds in Scala?
Answer:
object(index)
. How can you do that in scala?This topic is derived from How do I setup multiple type bounds in Scala?
Answer:
- scala> def process[R <: function1[Int,String] with Iterable[String]] (resource:R) = {
- | println("using function:"+resource(0))
- | println("using iterable:"+resource.elements.next)
- | }
- process: [R <: (int) => String with Iterable[String]](R)Unit
- // Array is a Function1 and iterable so this works
- scala> process (Array("1","2","3"))
- using function:1
- using iterable:1
Labels:
generic,
Scala,
type-bound,
with
Subscribe to:
Posts (Atom)