Scala Collections Series, Part 3 - Operations on Scala Collections, File I/O and Trivia
This blog post is the last of a three part series, this section covers:
- Operations on Scala Collections
- File I/O
- Trivia
Operations on Scala Collections
It’s possible to compose operations on collections, here are a few examples.
scala> val listOfSentences = List("'Tis better to have loved and lost than never to have loved at all. #lovedthanlost", "It ain't what you don't know that gets you into trouble, it's what you know for sure that just ain't so. #marktwain", "#moon #onesmallstepforman That's one small step for man, one giant leap for mankind.")
listOfSentences: List[String] = List('Tis better to have loved and lost than never to have loved at all. #lovedthanlost, It ain't what you don't know that gets you into trouble, it's what you know for sure that just ain't so. #marktwain, #moon #onesmallstepforman That's one small step for man, one giant leap for mankind.)
scala> val numberOfWords = listOfSentences.flatMap(_.split(" ")).size
numberOfWords: Int = 50
scala> val distinctWords = listOfSentences.map(_.filter(c => !Set(',', '.', '!', ',').contains(c))).flatMap(_.split(" ")).toSet
distinctWords: scala.collection.immutable.Set[String] = Set(it's, trouble, for, That's, giant, have, #lovedthanlost, step, than, mankind, sure, what, so, #moon, all, just, #marktwain, ain't, man, don't, lost, that, to, you, know, small, 'Tis, at, leap, #onesmallstepforman, loved, gets, It, into, better, and, one, never)
scala> distinctWords.size
res102: Int = 38
scala> val hashtags = listOfSentences.map(_.filter(c => !Set(',', '.', '!', ',').contains(c))).flatMap(_.split(" ")).filter(_.head == '#')
hashtags: List[String] = List(#lovedthanlost, #marktwain, #moon, #onesmallstepforman)
File I/O
Input file:
chevy
ford
tesla
ferrari
To read the above input file, named input.dat into a list:
import scala.io.Source
import java.io._
// get makes as a List of Strings
val makes = Source.fromFile("input.dat").getLines.toList
// get makes as a comma separated String
Source.fromFile("input.dat").getLines.mkString(",")
// Write the makes back to a file, separated by newline
val writer = new PrintWriter(new File("output.dat"))
makes.foreach(make => writer.write(make + "\n"))
writer.close()
Trivia
A few bits of trivia…
There are Set(1,2,3,4) and then a HashTrieSet:
scala> Set(1).getClass
res3: Class[_ <: scala.collection.immutable.Set[Int]] = class scala.collection.immutable.Set$Set1
scala> Set(1,2).getClass
res4: Class[_ <: scala.collection.immutable.Set[Int]] = class scala.collection.immutable.Set$Set2
scala> Set(1,2,3).getClass
res5: Class[_ <: scala.collection.immutable.Set[Int]] = class scala.collection.immutable.Set$Set3
scala> Set(1,2,3,4).getClass
res6: Class[_ <: scala.collection.immutable.Set[Int]] = class scala.collection.immutable.Set$Set4
scala> Set(1,2,3,4,5).getClass
res7: Class[_ <: scala.collection.immutable.Set[Int]] = class scala.collection.immutable.HashSet$HashTrieSet
Instead of checking emptiness using length, used the built in methods:
scala> "Bob".length > 0
res103: Boolean = true
scala> "Bob".nonEmpty
res104: Boolean = true
scala> "Bob".isEmpty
res105: Boolean = false
Don’t nest a match inside a map, use a partial function instead:
scala> List("Bob", "Tom").map { _ match { case s: String if s == "Tom" => true; case _ => false } }
res109: List[Boolean] = List(false, true)
scala> List("Bob", "Tom").map { case s: String if s == "Tom" => true; case _ => false }
res110: List[Boolean] = List(false, true)
Min/Max can replace reduceLeft if you’re looking for those values:
scala> List(1, 4, 5, 100).min
res111: Int = 1
scala> List(1, 4, 5, 100).max
res112: Int = 100