I have been trying to learn Scala in my free time and learn to write code in a more functional manner; anyways I have hit a problem trying to write (what I thought) would be a simple tool for reading formatted name data out of a file and creating a List of that data containing case classes... this does not work however:
object NameDataUtil {
/**
* reads a data file containing formatted name data into 开发者_运维知识库a list containing case classes.
*
* @param fileName name of the file (with extension) to read the data from.
* @return a list of case classes containing the data from the specified file.
*/
def readInFile(fileName: String): List[NameDatum] = {
val names: List[NameDatum] = Source.fromURL(getClass.getResource("/"+fileName)).getLines() foreach { line =>
line.trim.split("\\s+")
match {
case Array(name,freq,cumFreq,rank) => NameDatum(name, freq.toDouble, cumFreq.toDouble, rank.toInt)
}
}
names
}
}
Any help is greatly appreciated. Thanks!
Replace foreach
with map
and you'll get an Iterator[NameDatum]
. Add a toList
after getLines()
to get a List[NameDatum]
instead, though it's probably better to use toStream
and work with a Stream[NameDatum]
instead, if you expect the file to be too big to fit all in memory.
i think the problem is that you're using foreach, which has a return-type of unit; see the signature of foreach from the following: http://www.scala-lang.org/api/current/index.html#scala.collection.Iterator
def foreach (f: (A) ⇒ Unit): Unit
what would do the trick is map, you can see the method signature (as in the above link) is
def map [B] (f: (A) ⇒ B): Iterator[B]
so when you perform your match on each line, you will map the type A, which is the type of line (i.e., String) to the type B, which is your NameDatum.
also, something you might find interesting is that you can use a regex in a match... this would be an alternative to using the split, check out the technique at the following http://ikaisays.com/2009/04/04/using-pattern-matching-with-regular-expressions-in-scala/
精彩评论