So my short code snippet looks like the following:
Source.fromFile(fileName).getLines().foldLeft(List[CsvEntry]())((csvList, currentLine) =>
currentLine match {
case pattern(organisation,yearAndQuartal,medKF,trueOrFalse,name,money) => new CsvEntry(organisation,yearAndQuartal,medKF.toInt,trueOrFalse.toInt,name,money) :: csvList
case default => csvList
The "fileName" is only the Name of the file, but it doesn't matter for my question.
And my csvList is defined like this:
type csvList = List[CsvEntry]
val list: csvList = List()
my class look like this:
class CsvEntry(val organisation: String, val yearAndQuartal : String, val medKF:Int, val trueOrFalse: Int, val name: String, val money:String){
override def toString = s"$organisation, $yearAndQuartal, $medKF,$trueOrFalse, $name, $money"
So my question is, whenever I am loading a file and writing it to my csvList it works, but when I am loading another 2nd file the old content gets overwirtten.
How can I change it in order to not get overwirtten, so it should only add it to the preceding data ?
The call beginning Source.fromFile... returns a list that you should then combine with the next call.
For example:
List("filename1", "filename2").map(processFile).flatten
where processFile is:
def processFile(fileName: String) = {
Source.fromFile(fileName).getLines().foldLeft... all the code in question
}
Nothing here can possibly get "overwritten", since there's no mutable state. Your type csvList and csvList in your foldLeft call are two very different things: the former is the type, the latter is the parameter.
Each time your snippet is executed, it returns a list of your CSV objects of a particular file. As an immutable list.
What you want is:
Make a function out of your snippet: def readFile(name: String): List[CsvFile]
Call it on the two files and save results to vals
Concat the two lists: list1 ++ list2
Related
I'm practicing leetcode problems to perfect my kotlin syntax and am wondering why this code doesn't work. My question specifically is why doesn't my courses hashmap populate with this code.
Prerequisites is an array in this form [[0,1][0,3][4,5][6,7]] and if I print my variables for pre and post they print what I expect
But I'm trying to turn courses into an adjacency matrix like this {0: [1,3], 4: [5], 6: [7]}
and instead it just prints an empty set every time
class Solution {
fun canFinish(numCourses: Int, prerequisites: Array<IntArray>): Boolean {
val courses = HashMap<Int, MutableList<Int>>().withDefault{ mutableListOf<Int>() }
for ((pre, post) in prerequisites){
courses[pre]?.add(post)
}
print(courses)
return false
}
}
stdout: {}
[] does not give you the default value
From the docs of withDefault:
This implicit default value is used when the original map doesn't contain a value for the key specified and a value is obtained with Map.getValue function
If you want to get the default value, you need to use getValue instead of the index operator.
Using the index operator, you would just get null and because of the the null-safe operator, the add operation would not even be executed.
If you take a look at the relevant source code, you can see that the funxtionality get is not changed when using .withDefault but only getOrImplicitDefault returns the default value.
Getting the default does not set anything
Furthermore, when accessing courses.getValue(pre) in the loop, the Map will be empty. Because of the withDefault, it will return a MutableList where you can add elements but getting such a list and adding elements to it will not add the list to the Map. Reading and accessing an element does not insert it.
Simple solution
If you want to make sure the element is present in the Map, you can use courses[pre]=course.getValue(pre) before reading courses[pre]?:
class Solution {
fun canFinish(numCourses: Int, prerequisites: Array<IntArray>): Boolean {
val courses = HashMap<Int, MutableList<Int>>().withDefault{ mutableListOf<Int>() }
for ((pre, post) in prerequisites){
courses[pre] = courses.getValue(pre)
courses[pre]?.add(post)
}
print(courses)
return false
}
}
If the entry is set already, it will be set to itself (no change) and if it isn't set, it will be set to the default value (empty list).
dan1st's answer covers it - your default list is just returned, not put and returned, so it's not part of the map - but here's a different take to get that functionality:
val courses = HashMap<Int, MutableList<Int>>().run {
withDefault{ key ->
mutableListOf<Int>().also { put(key, it) }
}
}
So basically using the withDefault wrapper, using run so the map is this in the default value function, so you can add your list to the map before returning it. Then when you call courses.getValue(69) you'll get back a list that's already been inserted into the map
If you like, there's also a function that'll do this grouping for you, groupBy
val nums = arrayOf(
intArrayOf(0,1),
intArrayOf(0,3),
intArrayOf(4,5),
intArrayOf(6,7)
)
val groups = nums.groupBy(keySelector = { it[0] }, valueTransform = { it[1] })
println(groups)
>> {0=[1, 3], 4=[5], 6=[7]}
I have a list like the following:
val map_temp =
List(
(List("SRC_123","SRC_999"),"TRGT_123"),
(List("SRC_456"),"TRGT_456"),
(List("SRC_789"),"TRGT_789"),
(List("SRC_888"),"TRGT_888"),
)
I want to check whether SRC_999 exists in it.
I tried the following:
map_temp.foreach {
case(key, value) =>
if (key.contains("SRC_999")) {
print("yes exists")
}
}
This causes the following error
error: value contains is not a member of Any
case(key:Any, value) => if(key.contains("SRC_99"))
I have also tried this:
map_temp.foreach(a => if(a._1.contains("SRC_999")))
But this causes the following error:
error: value contains is not a member of Any
mapped.foreach(a => print(a._1.contains("SRC_999")))
How can I solve this?
How can I solve this?
By not having a List[Any].
By having a List[Any], you are explicitly telling Scala that the elements could be anything. That means Scala doesn't know anything about the elements. It doesn't even know whether they have a contains method or not. The elements could be integers, for example, which don't have a contains method.
The map_temp value is List[(List[String], String)], not List[Any]. You can check for the element you are looking for like this:
map_temp.exists(_._1.contains("SRC_999"))
This should do what you want:
val map_temp =
List(
(List("SRC_123","SRC_999"),"TRGT_123"),
(List("SRC_456"),"TRGT_456"),
(List("SRC_789"),"TRGT_789"),
(List("SRC_888"),"TRGT_888"),
)
def exists[A](input: List[(List[A], _)], what: A): Boolean =
input.exists(_._1.contains(what))
// should be found
assert(exists(map_temp, "SRC_999"))
assert(exists(map_temp, "SRC_888"))
// should not be found
assert(!exists(map_temp, "SRC_998"))
assert(!exists(map_temp, "TRGT_123"))
I don't think you actually have a List[Any] to begin with. It appears that you are experiencing a couple of type errors that could mislead you into believing so. Your map_temp is a List[(List[String], String)].
If that's not the case and you are getting map_temp from a method that for some reason returns a List[Any], if you're in control of that method you can change it to reflect the actual type. If you can't, even though it's not safe, you can attempt to cast it.
With few changes, you can also retrieve items:
def find[A, B](input: List[(List[A], B)], what: A): Option[B] =
input.find(_._1.contains(what)).map(_._2)
// should be found
assert(find(map_temp, "SRC_999") == Some("TRGT_123"))
assert(find(map_temp, "SRC_888") == Some("TRGT_888"))
// should not be found
assert(find(map_temp, "SRC_998") == None)
assert(find(map_temp, "TRGT_123") == None)
You can play around with this code here on Scastie.
I used graph dsl to create some stream processing jobs based on some example code I saw. Everything runs great, I am just having trouble understanding the notation: (updated for 2.4)
def elements: Source[Foos] = ...
def logEveryNSink = // a sink that logs
def cleaner: Flow[Foos, Bars, Unit] = ...
def boolChecker(bar: Bar)(implicit ex: ExecutionContext): Future[Boolean] = ...
val mySink = Sink.foreach[Boolean](println(_))
val lastly = Flow[Bars].mapAsync(2)(x => boolChecker(x).toMat(mySink)(Keep.right)
val materialized = RunnableGraph.fromGraph(
GraphDSL.create(lastly) { implicit builder =>
baz => {
import GraphDSL.Implicits._
val broadcast1 = builder.add(Broadcast[Foos](2))
val broadcast2 = builder.add(Broadcast[Bars](2))
elements ~> broadcast1 ~> logEveryNSink(1)
broadcast1 ~> cleaner ~> broadcast2 ~> baz
~> broadcast2 ~> logEveryNSink(1)
ClosedShape
}
}
).run()
I understand the implicit builder that is included, but Im uncertain what the baz represents in { implicit builder => baz => { .... is it just an implicit name for the entire shape?
The GraphDSL.create method is heavily overloaded to take in many variants of amounts of input shapes (including 0). If you pass in no initial shapes, then the signature of the buildBlock function arg (the body where you actually define how the graph is to be built) is as follows:
(Builder[NotUsed]) => S
So this is simply a Function1[Builder[NotUsed], S], that is, a function that takes an instance of a Builder[NotUsed] and returns a Shape instance which is the final graph. The NotUsed here is synonymous with Unit in that you are saying that by not passing in any input shares that you do not care about the materialized value of the output graph being produced.
If you do decide to pass in input shapes, then the signature of that buildBlock function changes a bit to accomadate the input shapes. In your case, you are passing in 1 input shape, so the signature of buildBlock changes to:
(Builder[Mat]) => Graph.Shape => S
Now, this is essentially a Function1[Builder[Mat], Function1[Graph.Shape, S]], or a function that takes a Builder[Mat] (where Mat is the materialized value type of the input shape) and returns a function that takes a Graph.Shape and returns an instance of S (which is a Shape).
Long story short, if you pass in shapes, then you also need to declare them as bound params on the graph building block function but as a second input function (hence the additional =>).
As I am working a design model, I am torn between two different methods of indicating a parameter of type List must be nonEmpty. I began by using List[Int] with an accompanying require statement to verify the List is nonEmpty.
case class A(name: String, favoriteNumbers: List[Int]) {
require(favoriteNumbers.nonEmpty, "favoriteNumbers must not be empty")
}
I then needed to make the list optional. If the List is provided, it must be nonEmpty. I'm using using Option[List[Int]] with an accompanying require statement to verify, if the Option is nonEmpty, the list must also be nonEmpty.
case class B(name: String, favoriteNumbers: Option[List[Int]]) {
require(
favoriteNumbers.isEmpty || favoriateNumbers.get.nonEmpty
, "when defined, favoriteNumbers.get must be nonEmpty"
)
}
However, I need to use this non-empty List all over the system I am modeling. This means that my code has these same require statements duplicated everywhere. Is there a (non-ScalaZ) way to have a new type, say NeList, which is defined and behaves identically to List, with the only change being an exception is thrown when NeList attempts to be instantiated with no elements?
I tried to Google for this and couldn't find a set of search terms to hone on this area. I either got really simple List how-tos, or all sorts of references to ScalaZ's NEL (Non Empty List). So, if there is a link out there that would help with this, I would love to see it.
If you
def foo[A](x: ::[A]) = "List has length "+x.length
then you insist that the list be nonempty. But of course your lists are all typed as List, so you need a helper method to give you a nonempty list:
implicit class NonEmptyList[A](private val underlying: List[A]) {
def ifNonEmpty[B](f: ::[A] => B): Option[B] = {
underlying match {
case x: ::[A #unchecked] => Some(f(x))
case _ => None
}
}
}
Now you can safely apply the operation to get an Option out. (You could also run side-effecting functions in a foreach-like method.)
Now, this is rather non-idiomatic Scala. But it is safe at compile time (the #unchecked notwithstanding--Scala's compiler isn't quite smart enough to realize that the type parameter hasn't changed).
You could implement a non-empty list yourself with implicit conversions between List[A] and Nel[A]:
case class Nel[A](val head: A, val tail: List[A] = Nil)
implicit def list2Nel[A](list: List[A]): Nel[A] = {
require(!list.isEmpty)
Nel(list.head, list.tail)
}
implicit def nel2List[A](nel: Nel[A]): List[A] = nel.head :: nel.tail
Then you can define your functions where this is needed such that they take a Nel[A] as a parameter:
def f(l: Option[Nel[String]]) = { ... }
And call them with normal lists (assuming the implicit defs are in scope):
f(Some(List("hello", "world")) // works
f(Some(Nil)) // throws IllegalArgumentException
f(None) // works
EDIT: It should be noted that this does not provide compile time guarantees that the List[A] passed in will not be empty. If that's what you want, then get rid of the implicit def list2Nel and require clients of your function to pass in an Nel[A] explicitly, thus guaranteeing at compile time that the list is not empty.
Also, this is a very basic NonEmptyList implementation. A more complete solution is found in scalaz (granted it was specifically requested in the question that scalaz not be used): https://github.com/scalaz/scalaz/blob/series/7.2.x/core/src/main/scala/scalaz/NonEmptyList.scala
How does this work in Scala?
val something = List(1,2,3)
List is abstract, and you can't construct it by invoking new List(), but List(1,2,3) works just fine.
Because it is a call to the apply method of the list companion object. In scala, a method called apply can be called with the method name ommitted (i.e. just with parens). It is by this mechanism that sequence and Map access works
Hence, List(1, 2, 3) is in fact:
List.apply(1, 2, 3)
So this is then a call to the apply method of List's companion object, the implementation of which is:
override def apply[A](xs: A*): List[A] = xs.toList
So you can see that apply is a method which takes a repeating parameter (a sequence), and calls the toList method on this sequence. This toList on Seq is inherited from TraversableOnce:
def toList: List[A] = new ListBuffer[A] ++= seq toList
So you can see that this creates a list via a ListBuffer and the ++= method:
override def ++=(xs: TraversableOnce[A]): this.type =
if (xs eq this) ++= (this take size) else super.++=(xs)
This ultimately gets its implementation of ++= from Growable:
def ++=(xs: TraversableOnce[A]): this.type = { xs.seq foreach += ; this }
Invoking new List() does not work because List is a trait (and a sealed one at that) - you would have had to apply implementations for the abstract methods. The fact that it is sealed means that it can only be implemented by a class in the same source file.
List(1,2,3) is "magic syntax" to call the apply method in the companion object of trait or class List.