How to apply this class code to a datafile which contains more than one record
class Iris(val sepal_len:Double,val sepal_width:Double,val petal_len:Double,
val petal_width:Double,var sepal_area:Double,val species:String){
require(sepal_area == sepal_len*sepal_width, "wrong values")
def this(sepal_len:Double,
sepal_width:Double,
petal_len:Double,
petal_width:Double,
species:String
) = {
this(sepal_len,sepal_width,petal_len,petal_width,sepal_len * sepal_width,species)
}
override def toString:String = "Iris("+sepal_len+","+sepal_width+","+petal_len+","+petal_width+
","+sepal_area+","+species + ")"
}
val ir = new Iris(1.2,3.4,4.5,5.0,4.08,"setosa")
Iris(1.2,3.4,4.5,5.0,4.08,setosa)
val ir1 = new Iris(1.2,3.4,4.5,5.0,"setosa")
output => ir1: Iris = Iris(1.2,3.4,4.5,5.0,4.08,setosa)
Please give me some idea
Use foreach and for every line create a collection of objects. maybe a list
I would suggest you to use case classed for such data structures and companion object for class overload.
case class Iris(sepal_len: Double, sepal_width: Double, petal_len: Double, petal_width: Double, sepal_area: Double, species: String) {
require(sepal_area == sepal_len * sepal_width, "wrong values")
}
object Iris {
def apply(sepal_len: Double, sepal_width: Double, petal_len: Double, petal_width: Double, species: String) =
new Iris(sepal_len, sepal_width, petal_len, petal_width, sepal_len * sepal_width, species)
}
val ir = Iris(1.2, 3.4, 4.5, 5.0, 4.08, "setosa")
val ir1 = Iris(1.2, 3.4, 4.5, 5.0, "setosa")
I've made the assumption that your sepal_area is not a required field in your class due to your examples and answered accordingly, but if it is required then changing the code will be easy.
In my example answer, I'm storing a collection of Iris. You could alternatively make a case class like:
case class Irises(irises: Seq[Iris])
Example CSV file:
1,5.1,3.5,1.4,5.1,Iris-setosa
2,4.9,3,1.4,9.8,Iris-setosa
3,4.7,3.2,1.3,14.1,Iris-setosa
4,4.6,3.1,1.5,Iris-setosa
5,5,3.6,1.4,25,Iris-setosa
6,5.4,3.9,1.7,32.4,Iris-setosa
Code:
object Demo extends App {
case class Iris(sepal_len: Double, sepal_width: Double, petal_len: Double,
petal_width: Double, var sepal_area: Double = 0, species: String) {
// if undefined on constructing the class
sepal_area = if(sepal_area == 0) sepal_len * sepal_width else sepal_area
def format(double: Double): Double = {
double.round
}
// had weird thing where 4.7 * 3 = 14.100000000000001
require(format(sepal_area) == format(sepal_len * sepal_width), "wrong values")
// using string concatenation looks much more readable
override def toString: String = s"Iris($sepal_len,$sepal_width,$petal_len,$petal_width,$sepal_area,$species)"
}
// file.csv found in {project-name}/file.csv
val bufferedSource = io.Source.fromFile("file.csv")
val seq = bufferedSource.getLines.map {
line =>
// for each line in csv file, split by comma and remove all whitespace around each part
val cols = line.split(",").map(_.trim)
// define parts
val sepal_len = cols.head.toDouble
val sepal_width = cols(1).toDouble
val petal_len = cols(2).toDouble
val petal_width = cols(3).toDouble
val species = if(cols.length == 6) cols(5) else cols(4)
// if sepal_area is defined
if (cols.length == 6) Iris(sepal_len, sepal_width, petal_len, petal_width, cols(4).toDouble, species)
// if sepal_area is not defined
else Iris(sepal_len, sepal_width, petal_len, petal_width, species = species)
}.toSeq
seq.foreach(println)
// Iris(1.0,5.1,3.5,1.4,5.1,Iris-setosa)
// Iris(2.0,4.9,3.0,1.4,9.8,Iris-setosa)
// Iris(3.0,4.7,3.2,1.3,14.1,Iris-setosa)
// Iris(4.0,4.6,3.1,1.5,18.4,Iris-setosa)
// Iris(5.0,5.0,3.6,1.4,25.0,Iris-setosa)
// Iris(6.0,5.4,3.9,1.7,32.4,Iris-setosa)
val newSeq = seq.toSeq
newSeq.foreach(println)
// close the source once you've finished with it
bufferedSource.close
}
Here is an entropy calculation based on an answer by Jeff Atwood : How to calculate the entropy of a file? which is based on http://en.wikipedia.org/wiki/Entropy_(information_theory) :
object MeasureEntropy extends App {
val s = "measure measure here measure measure measure"
def entropyValue(s: String) = {
val m = s.split(" ").toList.groupBy((word: String) => word).mapValues(_.length.toDouble)
var result: Double = 0.0;
val len = s.split(" ").length;
m map {
case (key, value: Double) =>
{
var frequency: Double = value / len;
result -= frequency * (scala.math.log(frequency) / scala.math.log(2));
}
}
result;
}
println(entropyValue(s))
}
I'd like to improve this by removing the mutable state relating to :
var result: Double = 0.0;
How to combine the result into a single calculation over the map function ?
Using foldLeft, or in this case /: which is a syntactic sugar for it:
(0d /: m) {case (result, (key,value)) =>
val frequency = value / len
result - frequency * (scala.math.log(frequency) / scala.math.log(2))
}
Docs: http://www.scala-lang.org/files/archive/api/current/index.html#scala.collection.immutable.Map#/:B(op:(B,A)=>B):B
A simple sum will do the trick:
m.map {
case (key, value: Double) =>
val frequency: Double = value / len;
- frequency * (scala.math.log(frequency) / scala.math.log(2));
}.sum
It can be written using foldLeft like below.
def entropyValue(s: String) = {
val m = s.split(" ").toList.groupBy((word: String) => word).mapValues(_.length.toDouble)
val len = s.split(" ").length
m.foldLeft(0.0)((r, t) => r - ((t._2 / len) * (scala.math.log(t._2 / len) / scala.math.log(2))))
}
I am working on Scala to convert list of lists to list of customized object "Point"
class Point(val x: Int, val y: Int) {
var cX: Int = x
var cY: Int = y
}
Should I use Foreach or should I use Map or foreach in this case
def list_To_Point(_listOfPoints :List[List[String]]) : List[Point] = {
var elem =
lazy val _list: List[Point] = _listOfPoints.map(p=> new Point(p[0],p[1])
_list
}
I couldn't figure out where the problem exactly ?
def listToPoint(l:List[List[String]]):List[Point] =
l.collect({case x::y::Nil => new Point(x.toInt,y.toInt)})
But you really shouldn't use a List[String] to represent what is basically (Int,Int) …
ugly as hell and untested but it should work (pls consider making your structures immutable) :
case class Point(x:Int,y:Int)
object Point {
def listToPoint(listOfPoints:List[List[String]]):List[Point] =
listOfPoints.map(p => new Point(p(0).toInt,p(1).toInt))
}
I must handle with sequences of orders (here Int for simplification):
// the handleOrder methods are in fact much more complicated:
def handleOrders(prev: Double, orders: Seq[Int]): Double = prev + orders.sum
def handleOrder(prev: Double, order: Int): Double = prev / order
As a result from a so called
def nextGroup(prev: Double, orders: Seq[Int]): Seq[Double]
function I get a sequence of another class (here Double for simplification).
From this I've implemented two versions.
Version 1 (foldLeft and explicit builder):
def nextGroup1(prev: Double, orders: Seq[Int]): Seq[Double] = {
import collection.mutable.Builder
import collection.immutable.VectorBuilder
val bld: Builder[Double, Seq[Double]] = new VectorBuilder[Double]
var first = true
orders.foldLeft(prev) { (prev, order) =>
val step = if (first) handleOrders(prev, orders) else prev
val next = handleOrder(step, order)
first = false
bld += next
next
}
bld.result
}
Version 2 (var and for yield builder):
def nextGroup2(prev: Double, orders: Seq[Int]): Seq[Double] = {
var first = true
var präv = prev
for (order <- orders) yield {
if (first) präv = handleOrders(präv, orders)
präv = handleOrder(präv, order)
first = false
präv
}
}
I'd like to save either explicit builder in version 1 or mutable var in version 2.
Is this possible? Perhaps with a combination of foldLeft and for-yield?
And still something sample data:
val orders = Seq(1, 2, 3)
nextGroup1(1d, orders) // => Vector(7.0, 3.5, 1.1666666666666667)
nextGroup2(1d, orders) // => List(7.0, 3.5, 1.1666666666666667)
nextGroup1(2d, orders) // => Vector(8.0, 4.0, 1.3333333333333333)
nextGroup2(2d, orders) // => List(8.0, 4.0, 1.3333333333333333)
The nextGroup results handled as Seq[Double], so Vector or List is no difference.
orders.tail.scanLeft(handleOrders(prev, orders)) { (p, o) => handleOrder(p, o) }
scanLeft does the same as foldLeft does but keeps all intermediate results. You can get rid of the special case by excluding the head of the collection which you can do using orders.tail.
I'm trying to create a class that has a map of keys -> function calls, and the following code is not behaving as I would like it to.
class MyClass {
val rnd = scala.util.Random
def method1():Double = {
rnd.nextDouble
}
def method2():Double = {
rnd.nextDouble
}
def method3():Double = {
rnd.nextDouble
}
def method4():Double = {
rnd.nextDouble
}
def method5():Double = {
rnd.nextDouble
}
var m = Map[String,Double]()
m += {"key1"-> method1}
m += {"key2"-> method2}
m += {"key3"-> method3}
m += {"key4"-> method4}
m += {"key5"-> method5}
def computeValues(keyList:List[String]):Map[String,Double] = {
var map = Map[String,Double]()
keyList.foreach(factor => {
val value = m(factor)
map += {factor -> value}
})
map
}
}
object Test {
def main(args : Array[String]) {
val b = new MyClass
for(i<-0 until 3) {
val computedValues = b.computeValues(List("key1","key4"))
computedValues.foreach(element => println(element._2))
}
}
}
The following output
0.022303440910331762
0.8557634244639081
0.022303440910331762
0.8557634244639081
0.022303440910331762
0.8557634244639081
indicates that once the function is placed in the map, it's a frozen instance (each key producing the same value for each pass). The behavior I would like to see is that the key would refer to a function call, generating a new random value rather than just returning the instance held in the map.
The problem is with the signature of your map m. You described that you wanted to put functions in the map; however you've declared it as Map[String, Double] which is just a map of strings to doubles. The correct type would be Map[String, () => Double].
Because brackets are optional on no-arg method invocations, the difference in types here is very important. When the map is being populated, the methods are invoked at insertion time in order to match the type signature (I believe this is done by an implicit conversion but I'm not 100% sure).
By simply changing the declared signature of your map, the functions are inserted as you desire, and can be evaluated during computeValues (requires a change on line 35 to map += {factor -> value()}), resulting in the following output (tested on Scala 2.8):
0.662682479130198
0.5106611727782306
0.6939805749938253
0.763581022199048
0.8785861039613938
0.9310533868752249
You need to map the keys to functions, not to the answer that the function would give you. Try this:
var m = Map[String,() => Double]()
m += /* etc. */
m.values.foreach(println(x => x()))
m.values.foreach(println(x => x()))
I would use scala's type inference to define the map.
There's no need to define the methods separately, if they're only used via the map.
Also you can use an immutable val, instead of a mutable var.
val m = Map( "key1" -> {() => rnd.nextDouble},
"key2" -> {() => rnd.nextDouble},
"key3" -> {() => rnd.nextDouble},
"key4" -> {() => rnd.nextDouble},
"key5" -> {() => rnd.nextDouble})
You also need to change line 35 to value()