I want get first element of my:
var stack = List[Map[String, ExpValue]]()
How is it possible that I always get an error that it is empty although I do this:
if (stack.isEmpty) {
var new_map:Map[String, ExpValue] = Map();
new_map::stack;}
var x = stack.head
Basically if it is empty add an element.
Why is head always empty?
Prepending list with element does not mutate the list, it creates a new one which contains new element followed by elements of the original list. In this case you can assign result of new_map :: stack to your stack variable:
var stack = List[Map[String, ExpValue]]()
if (stack.isEmpty) {
var new_map: Map[String, ExpValue] = Map();
stack = new_map :: stack;
}
var x = stack.head
Values come in many different shapes but mechanisms to deal with them are the same. For example, consider the behaviour of operations + and :: in the following snippet
val x: Int = 41
1 + x
x
// res0: Int = 41
val l: List[Int] = List(41)
1 :: l
l
// res1: List[Int] = List(41)
List(41) is a value in the same sense 41 is a value, and res1 remains List(41) instead of List(1, 41) for the same reasons res0 remains 41 instead of 42.
Applying this concept to your snippet (after simplifying it a bit)
val stack: List[Map[String, Int]] = List()
Map() :: stack
stack
// res2: List[Map[String,Int]] = List()
can you see why res2 remains List() instead of List(Map())?
Related
we had to implement the insert function that can insert a cell into a sorted linked list. My implementation idea was to have two rlists, called previous and current, that will be used to iterate through the list. At the beginning of the function call, the previous rlist will contain a random integer, and its next field is pointing to the current cell which is the head of the linked_list. I think this is problematic. I finished implementing my idea. I think the method will add the correct integer at the right place in the linked list. However, if the inserted element is at the beginning of the list, then the list is still the old list when using displaying on to the screen, but the old list does indeed have a cell pointing to it, and that cell has the inserted integer. So I'm not sure how to deal with that.
I tested my method, and it doesn't work as I described.
Here is what I did: I inserted -9 to the end of c3. c3 does indeed get -9 at the end of the list. And then I added 4 inside c5. But then c5 now becomes [5;4;-9]. So it is wrong, it should have [5;4;3;2;1;-9] instead. So I don't know what is wrong.
I looked up online on how to implement the method so that they can give me some inspirations or hint, but the solutions they provided are usually in Java or other programming languages.
type cell = { data : int; next : rlist}
and rlist = cell option ref
let c1 = {data = 1; next = ref None}
let c2 = {data = 2; next = ref (Some c1)}
let c3 = {data = 3; next = ref (Some c2)}
let c5 = {data = 5; next = ref (Some c3)}
let rec displayList (c : rlist) =
match !c with
| None -> []
| Some { data = d; next = l } -> d :: (displayList l)
let cell2rlist (c : cell) :rlist = ref (Some c)
let bigger((x:int), (y:int)) = (x > y)
let insert (comp : (int * int) -> bool) (item : int) (listt :rlist)=
let itemm = {data=item ; next = ref None} in
let rec helper (prev : rlist) (item : cell) (current: rlist) funcc =
match !current with
|None -> (match !prev with
|Some w -> w.next := (Some itemm))
|Some q -> if comp (item.data, q.data) then (itemm.next := (Some q) ; match !prev with
|Some w -> w.next := (Some itemm))
else prev := !current; current:= !(q.next); (helper prev item current funcc)
in let previous = ref (Some {data=0; next = listt}) in
helper previous itemm listt comp
Here are examples of the right return values for the code in action:
let l5 = cell2rlist c5;;
val l5 : rlist = ....
(* Messy display deleted. *)
displayList l5;;
- : int list = [5; 3; 2; 1]
displayList l5;;
- : int list = [5; 3; 2; 1]
insert bigger 4 l5;;
- : unit = ()
displayList l5;;
- : int list = [5; 4; 3; 2; 1]
insert bigger 9 l5;;
- : unit = ()
displayList l5;;
- : int list = [9; 5; 4; 3; 2; 1]
insert bigger 0 l5;;
- : unit = ()
displayList l5;;
- : int list = [9; 5; 4; 3; 2; 1; 0]
But when I ran my codes, here is what I get:
insert bigger 10 (ref(Some c5)) ;;
- : unit = ()
c5 ;;
- : cell =
{data = 5;
next =
{contents =
Some
{data = 3;
next =
{contents =
Some
{data = 2;
next = {contents = Some {data = 1; next = {contents = None}}}}}}}}
As you can see, if I insert a number that is supposed to be inserted at the beginning of the list, I can't see it.
Here is another example,
insert bigger 4 (ref(Some c5)) ;;
- : unit = ()
c5 ;;
- : cell =
{data = 5;
next =
{contents =
Some
{data = 4;
next = {contents = Some {data = 1; next = {contents = None}}}}}}
So as you see the code doesn't work at all as the updated list should have values [5;4;3;2;1] but it has [5;4;1] instead.
Here is another example:
insert bigger (-9) (ref(Some c3)) ;;
- : unit = ()
c3 ;;
- : cell =
{data = 3;
next =
{contents =
Some
{data = 2;
next =
{contents =
Some
{data = 1;
next = {contents = Some {data = -9; next = {contents = None}}}}}}}}
So it seems that the method does insert the element correctly into the list, but the lists that the inserted cell suppose to point to seem to be wrong.
For reference, here is a session showing a failure of your code:
# let (l: rlist) = ref None;;
val l : rlist = {contents = None}
# insert bigger 1 l;;
- : unit = ()
# l;;
- : rlist = {contents = Some {data = 1; next = {contents = None}}}
# insert bigger 0 l;;
- : unit = ()
# l;;
- : rlist = {contents = None}
For what it's worth, it would also be good if your code was indented properly.
At any rate, what I see when I look at your code for a short time is this fragment:
current:= !(q.next);
helper prev item current funcc
It looks to me like you're imagining that the first line here will advance some local variable to point to the next element of the list. But what it actually is doing is modifying the list.
You might want something more like this:
helper prev item q.next funcc
There are other problems in your code as well. It seems odd, for example, that the then part is parenthesized but the else part isn't parenthesized.
I have 2 Lists as mentioned below:
val L1 = List[(Int,Int,String)]
val L2 = List[(Int,Int,String)]
I want to join these 2 lists on the basis of 1st and 2nd Int element in a way that result list must have 4 elements (Int,Int,String,String).
val joinedList = List[(Int, Int, String, String)]
where last 2 String elements will be string from L1 and string from L2.
Ex:-
val L1 = List((1,1,"one"), (2,2,"two"))
val L2 = List((2,2,"twice"), (3,3,"thrice"))
Output List ->
val joinedList = List((1,1,"one","--"),(2,2,"two","twice"), (3,3,"--","thrice"))
Kindly suggest a way to achieve that in scala.
First you want to get it into Maps, so it's easier to look up, then you can just map over all the keys:
val L1Map = L1.map{case (x,y,z) => ((x,y) -> z)}.toMap
val L2Map = L2.map{case (x,y,z) => ((x,y) -> z)}.toMap
val allKeys = L1Map.keySet ++ L2Map.keySet
val result = allKeys map {case (x,y) =>
(x, y, L1Map.getOrElse((x,y), "--"), L2Map.getOrElse((x,y), "--"))
}
That gives you an unsorted Set as a result. If you need a List, you can convert it back and sort it as necessary.
Lets take an example where store is my class.
class store(val a:Int) { }
In the code i want to create a list of store.
val list : List[store] = new List[store]()
How can i add a store in the same list?
First off, it's usually a good idea to capitalize your class names.
scala> class Store(val a:Int) { }
defined class Store
scala> val list : List[Store] = List.empty
list: List[Store] = List()
scala> val newList = new Store(4) :: list
newList: List[Store] = List(Store#243306de)
Your list is, by default, immutable so you'll have a new list every time an element is added.
scala> val newerList = new Store(71) :: newList
newerList: List[Store] = List(Store#30f57af0, Store#243306de)
ADDENDUM
If you need a mutable list (not usually recommended) you could try the following.
scala> import scala.collection.mutable.MutableList
import scala.collection.mutable.MutableList
scala> val myList: MutableList[Store] = MutableList.empty
myList: scala.collection.mutable.MutableList[Store] = MutableList()
scala> myList += new Store(56)
res322: myList.type = MutableList(Store#6421614e)
scala> myList += new Store(29)
res323: myList.type = MutableList(Store#6421614e, Store#85b26)
scala> myList += new Store(11)
res324: myList.type = MutableList(Store#6421614e, Store#85b26, Store#5d2f7883)
Mutable variables are considered poor style and an impediment to proper Functional Programming.
To add element to the beginning of the list use :: :
val l = List(1, 2, 3)
val l1 = 5 :: l // List(5, 1, 2, 3)
or
val l1 = l.::(5)
To add element to the end of the list use :+ :
val l2 = l :+ 5 // List(1, 2, 3, 5)
So, to add store object to the end of the list (though it is not efficient), write this:
val s = new Store(1)
val newList = list :+ s // list is immutable
Let's say that I have a Map of strings -> List of Integers. I would like to create a function which takes in as a parameter a List of strings and returns all the integers correlating to all the string in that list. I.e. if the Map X contains the following mappings:
database = [("Bob",[1,2,3]),("John",[1,5,6]),("Trevor",[4,5,7])]
If this function takes in ["Bob","John"] as the list of names, it should return,
[1,2,3,5,6]
Since Bob correlates to 1,2,3 and John correlates to 1,5,6 (same entries for both names aren't duplicated). I also would like to not introduce a mutable variable if I don't have to, thus leading me to believe a for comprehension that yields this list of number values would be the best way to achieve this, but I'm not sure how.
If you want to use a for-comprehension you can so this:
val result = for {
key <- keys
nums <- map.get(key).toSeq
num <- nums
} yield num
result.distinct
Explanation:
for each key in the list try to get an entry and convert it to a Seq (necessary because flatMap expects a Seq in this case) and add every number in the list to the result. If the key is not present in the map the collection will be empty and therefore not yield any results. At the end call distinct to remove the duplicates.
val myMap = Map("Bob" -> List(1,2,3), "John" -> List(1,5,6), "Trevor" -> List(4,5,7))
val names = List("Bob", "John")
You can add default value to Map using method withDefaultValue:
val mapWithDefaul = myMap withDefaultValue Nil
Then you could use Map as function in flatMap:
names.flatMap(mapWithDefaul).distinct
// List(1, 2, 3, 5, 6)
Let
val db = Map("Bob" -> List(1,2,3), "John" -> List(1,5,6), "Trevor" -> List(4,5,7))
val names = List("Bob", "John")
Then a similar approach to #senia's using flatMap,
implicit class mapCorr[A,B](val db: Map[A,List[B]]) extends AnyVal {
def corr(keys: List[A]): List[B] = {
keys.flatMap{ k => db get k }.flatten.distinct
}
}
and
scala> db.corr(keys)
res0: List[Int] = List(1, 2, 3, 5, 6)
Here we allow for key lists of type A and maps from type A to type List[B] .
val myset = Set("Bob","John")
val database = Map(("Bob"->List(1,2,3)),("John"->List(1,5,6)),("Trevor"->List(4,5,7)))
val ids = database.filter(m => myset.contains(m._1)).map(_._2).flatten.toList.distinct
outputs:
ids: List[Int] = List(1, 2, 3, 5, 6)
Something like:
val result = database.filter(elem => list.contains(elem._1)).foldLeft(List())((res,elem) => res ++ elem._2)
where list is the input list of names.
I did "mkString" but still can not print list of strings. With input line:
9002194187,2644,54,100,3,4,2,5
I get the following output:
Line: 9002194187,2644,54,100,3,4,2,5
StrArr: 9002194187,2644,54,100,3,4,2,5
Lst: [Ljava.lang.String;#223d2e6c
Lst again: List([Ljava.lang.String;#223d2e6c)
Lst1: [Ljava.lang.String;#223d2e6c
Result: foo
From the code below:
def mkRecord(line: String) : String = {
val klass = "foo"
val strArr = line.split(",") // convert string to array of strings
println("Line: "+line)
println("StrArr: "+strArr.mkString(","))
val lst = List(strArr)
println("Lst: "+lst.mkString(" - "))
println("Lst again: "+lst)
val lst1 = lst.tail ++ List(klass) // attribute list except for the first one, plus new klass attribute
println("Lst1: "+lst.mkString(" , "))
val result = lst1.mkString(",") // attribute string
println("Result: "+ result)
return result
}
Please, help. I am at complete loss (
The constructor for List (actually, the apply method on the List companion object) takes parameters in the form of scala's "varargs" equivalent:
def apply[A](xs: A*): List[A] // some irrelevant details have been elided
In java, this would be written something like:
public static List<A> apply(A... args)
In scala this can be called using any Seq (or subclass), but using a special notation. The line you used:
val lst = List(strArr)
creates a List[Array[String]], with a single entry - the array strArr. To tell the compiler to turn the array into a varargs when passing it to the List apply method, add : _* on the end (the space is optional):
val lst = List(strArr: _*)
This change in your code will result in:
scala> mkRecord(chkStr)
Line: 9002194187,2644,54,100,3,4,2,5
StrArr: 9002194187,2644,54,100,3,4,2,5
Lst: 9002194187 - 2644 - 54 - 100 - 3 - 4 - 2 - 5
Lst again: List(9002194187, 2644, 54, 100, 3, 4, 2, 5)
Lst1: 9002194187 , 2644 , 54 , 100 , 3 , 4 , 2 , 5
Result: 2644,54,100,3,4,2,5,foo
res1: String = 2644,54,100,3,4,2,5,foo
You can turn any array into a list with its toList operator, avoiding this problem (the nature of which Shadowlands has explained). You can do string -> array -> list in one line:
line.split(',').toList
Using a collection's toList method is often going to be faster than extracting all the elements into a sequence and then converting that sequence into a list, not least because you'll be using a method optimised for the source collection. However, that's an optimisation which you can worry about after the priorities of success and clarity.