Last active
September 30, 2015 16:57
-
-
Save jasonbaldridge/1830413 to your computer and use it in GitHub Desktop.
The code to accompany a blog post about List computations: http://bcomposes.wordpress.com/2012/02/14/variations-for-computing-results-from-sequences-in-scala/
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// This is code to accompany my blog post about variations on sequence computations: | |
// http://bcomposes.wordpress.com/2012/02/14/variations-for-computing-results-from-sequences-in-scala/ | |
// | |
// Jason Baldridge | |
// A function to display the results of various ways of doing the same thing. | |
def display (intro: String, wlengths: List[Int], wcaps: List[Boolean]) { | |
println(intro) | |
println("Lengths: " + wlengths.mkString(" ")) | |
println("Caps: " + wcaps.mkString(" ")) | |
println | |
} | |
// The list of words to use. | |
val words = List("This", "is", "a", "list", "of", "English", "words", ".") | |
// ***************************************************************************** | |
// The functional way | |
val (wlengthsMapUnzip, wcapsMapUnzip) = | |
words.map(word => (word.length, word(0).isUpper)).unzip | |
display("Using map and unzip.", | |
wlengthsMapUnzip, wcapsMapUnzip) | |
// ***************************************************************************** | |
// Using reassignable lists | |
var wlengthsReassign = List[Int]() | |
var wcapsReassign = List[Boolean]() | |
words.foreach { word => | |
wlengthsReassign = word.length :: wlengthsReassign | |
wcapsReassign = word(0).isUpper :: wcapsReassign | |
} | |
display("Using reassignable lists.", | |
wlengthsReassign.reverse, wcapsReassign.reverse) | |
// ***************************************************************************** | |
// Using a mutable ListBuffer | |
import collection.mutable.ListBuffer | |
val wlengthsBuffer = ListBuffer[Int]() | |
val wcapsBuffer = ListBuffer[Boolean]() | |
words.foreach { word => | |
wlengthsBuffer.append(word.length) | |
wcapsBuffer.append(word(0).isUpper) | |
} | |
display("Using mutable ListBuffer.", | |
wlengthsBuffer.toList, wcapsBuffer.toList) | |
// ***************************************************************************** | |
// The imperative way | |
val wlengthsArray = Array.fill(words.length)(0) | |
val wcapsArray = Array.fill(words.length)(false) | |
words.indices.foreach { index => | |
wlengthsArray(index) = words(index).length | |
wcapsArray(index) = words(index)(0).isUpper | |
} | |
display("Using iteration and arrays.", wlengthsArray.toList, wcapsArray.toList) | |
// ***************************************************************************** | |
// The imperative way without the cost of indexing into Lists | |
val wlengthsArray2 = Array.fill(words.length)(0) | |
val wcapsArray2 = Array.fill(words.length)(false) | |
var index = 0 | |
words.foreach { word => | |
wlengthsArray2(index) = word.length | |
wcapsArray2(index) = word(0).isUpper | |
index += 1 | |
} | |
// ***************************************************************************** | |
// As above, but using zipWithIndex to iterate over (word,index) pairs. | |
val wlengthsArray3 = Array.fill(words.length)(0) | |
val wcapsArray3 = Array.fill(words.length)(false) | |
words.zipWithIndex.foreach { case(word,index) => | |
wlengthsArray3(index) = word.length | |
wcapsArray3(index) = word(0).isUpper | |
} | |
// ***************************************************************************** | |
// Using a predefined function | |
def getLengthAndUpper = (word: String) => (word.length, word(0).isUpper) | |
val (wlengthsFunction, wcapsFunction) = words.map(getLengthAndUpper).unzip | |
display("Using a predefined function.", | |
wlengthsFunction.toList, wcapsFunction.toList) | |
// ***************************************************************************** | |
// Using for expressions | |
val (wlengthsFor, wcapsFor) = | |
(for (word <- words) yield (word.length, word(0).isUpper)).unzip | |
display("Using a for expression.", | |
wlengthsFunction.toList, wcapsFunction.toList) | |
// ***************************************************************************** | |
// Using a recursive function | |
// This is a recursive function that builds up the lengths and caps lists. | |
def lengthCapRecursive( | |
inputWords: List[String], | |
lengths: List[Int], | |
caps: List[Boolean]): (List[Int], List[Boolean]) = inputWords match { | |
case Nil => | |
(lengths, caps) | |
case head :: tail => | |
lengthCapRecursive(tail, head.length :: lengths, head(0).isUpper :: caps) | |
} | |
// This is a "wrapper" for the above recursive functin that calls that function | |
// with empty lists, gets the results, and returns the reverse of each list. | |
def lengthCapRecursive(inputWords: List[String]): (List[Int], List[Boolean]) = { | |
val (l,c) = lengthCapRecursive(words, List[Int](), List[Boolean]()) | |
(l.reverse, c.reverse) | |
} | |
val (wlengthsRecursive, wcapsRecursive) = lengthCapRecursive(words) | |
display("Using a recursive function.", | |
wlengthsRecursive, wcapsRecursive) | |
// ***************************************************************************** | |
// Using a recursive function that is contained in the wrapper function | |
def lengthCapRecurWrap(inputWords: List[String]): (List[Int], List[Boolean]) = { | |
// This function is hidden from code that doesn't | |
def lengthCapRecurHelp( | |
inputWords: List[String], | |
lengths: List[Int], | |
caps: List[Boolean]): (List[Int], List[Boolean]) = inputWords match { | |
case Nil => | |
(lengths, caps) | |
case head :: tail => | |
lengthCapRecurHelp(tail, head.length :: lengths, head(0).isUpper :: caps) | |
} | |
val (l,c) = lengthCapRecurHelp(words, List[Int](), List[Boolean]()) | |
(l.reverse, c.reverse) | |
} | |
val (wlengthsRecurWrap, wcapsRecurWrap) = lengthCapRecurWrap(words) | |
display("Using a recursive function contained in a wrapper.", wlengthsRecurWrap, wcapsRecurWrap) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment