How to add an element to list in scala? - scala

I am trying to add an element to a range in scala. Why does the following code snippet fail? What's the right way to do it?
import scala.collection.mutable.ListBuffer
val range = Range(1, 10)
val buffer = ListBuffer()
buffer.appendAll(range)

You haven't informed the compiler what type elements buffer will hold.
val buffer = ListBuffer[Int]()
After that the appendAll() should work fine. But there's nothing in your code that will "add an element to a range" (or a list, as the question title falsely indicates). That's a different operation.
You can pre-pend or append a new element but you get an IndexedSeq[Int] back.
0 +: range
range :+ 14
If you want a real Range you can build a new one.
val biggerRange = Range(range.start - 1 , range.end + 2, range.step)

ListBuffer appenAll need traversable object.
https://www.scala-lang.org/api/current/scala/collection/TraversableOnce.html
Workaround is to use -
val buffer = ListBuffer[Int]()
for (i <- range ) buffer.append(i)

Related

Broadcasting of scala options on sub-elements [duplicate]

I am new to scala, please help me with the below question.
Can we call map method on an Option? (e.g. Option[Int].map()?).
If yes then could you help me with an example?
Here's a simple example:
val x = Option(5)
val y = x.map(_ + 10)
println(y)
This will result in Some(15).
If x were None instead, y would also be None.
Yes:
val someInt = Some (2)
val noneInt:Option[Int] = None
val someIntRes = someInt.map (_ * 2) //Some (4)
val noneIntRes = noneInt.map (_ * 2) //None
See docs
You can view an option as a collection that contains exactly 0 or 1 items. Mapp over the collection gives you a container with the same number of items, with the result of applying the mapping function to every item in the original.
Sometimes it's more convenient to use fold instead of mapping Options. Consider the example:
scala> def printSome(some: Option[String]) = some.fold(println("Nothing provided"))(println)
printSome: (some: Option[String])Unit
scala> printSome(Some("Hi there!"))
Hi there!
scala> printSome(None)
Nothing provided
You can easily proceed with the real value inside fold, e.g. map it or do whatever you want, and you're safe with the default fold option which is triggered on Option#isEmpty.

In scala, how do I get access to specific index in tuple?

I am implementing function that gets random index and returns the element at random index of tuple.
I know that for tuple like, val a=(1,2,3) a._1=2
However, when I use random index val index=random_index(integer that is smaller than size of tuple), a._index doesnt work.
You can use productElement, note that it is zero based and has return type of Any:
val a=(1,2,3)
a.productElement(1) // returns 2nd element
If you know random_index only at runtime the best what you can have is (as #GuruStron answered)
val a = (1,2,3)
val i = 1
val x = a.productElement(i)
x: Any // 2
If you know random_index at compile time you can do
import shapeless.syntax.std.tuple._
val a = (1,2,3)
val x = a(1)
x: Int // 2 // not just Any
// a(4) // doesn't compile
val i = 1
// a(i) // doesn't compile
https://github.com/milessabin/shapeless/wiki/Feature-overview:-shapeless-2.0.0#hlist-style-operations-on-standard-scala-tuples
Although this a(1) seems to be pretty similar to standard a._1.

Scala ordered priority queue that always has the lowest number as the head, ascending order

I'd like to get a code sample that accomplishes ascending ordering of items in a priority queue.
I'd like to store Tuple2(Int, String) inside a priority queue so that it is ordered by the first element of the tuple in ascending order.
If my priority queue is called pq and I call pq.head I'd like to get the tuple with the lowest number, same thing with calling pq.dequeue.
scala> val pq = scala.collection.mutable.PriorityQueue[(Int, String)]()
pq: scala.collection.mutable.PriorityQueue[(Int, String)] = PriorityQueue()
scala> pq += Tuple2(8, "eight")
res60: pq.type = PriorityQueue((8,eight))
scala> pq += Tuple2(4, "four")
res61: pq.type = PriorityQueue((8,eight), (4,four))
scala> pq += Tuple2(7, "seven")
res62: pq.type = PriorityQueue((8,eight), (4,four), (7,seven))
How to apply ascending ordering by first element at time of insertion to the above?
Thanks
PriorityQueue.apply and PriorityQueue.empty both take an implicit Ordering instance that will be used to order the contents—the head will be the "largest" value according to that ordering. You're getting the default one for tuples, which is a lexicographic ordering on the elements of the tuple, which isn't what you want, since it'll make the tuple with the largest first element the head.
There are a couple of ways you can solve this issue. The easiest is just to call .reverse on your queue, which will give you a new queue with the same contents but the opposite ordering, which means the tuple with the lowest value will be the head.
You can also provide your own ordering when creating the queue:
import scala.collection.mutable.PriorityQueue
val pq = PriorityQueue.empty[(Int, String)](
implicitly[Ordering[(Int, String)]].reverse
)
Or if you explicitly don't want the second element to be consulted:
val pq = PriorityQueue.empty[(Int, String)](
Ordering.by((_: (Int, String))._1).reverse
)
This is possibly a little more efficient than reversing the queue, but probably not enough to worry about, so you should just choose the approach that you find most elegant.
If all you need is reversing the implicit ordering, you could just reverse the queue right away:
val pq = PriorityQueue.empty[(Int, String)].reverse
All you need to do is to mention ordering of the queue items. The following code will serve the purpose.
def ascendingOrder(tuple2: (Int, String)) = -tuple2._1
val pq = PriorityQueue[(Int, String)]()(Ordering.by(ascendingOrder))
pq += Tuple2(8, "eight")
pq += Tuple2(4, "four")
pq += Tuple2(7, "seven")
for (i <- 1 to 3) (println(pq.dequeue()))
Avoid using reverse as it will create unnecessary overheads.
From the scaladoc:
Only the dequeue and dequeueAll methods will return methods in priority order (while removing elements from the heap). Standard collection methods including drop and iterator will remove or traverse the heap in whichever order seems most convenient.
That caveat seems to also apply to .head, but .dequeue returns elements in order.
The default ordering is descending (since the highest priority comes out first), but you can explicitly pass a reversed order when constructing:
val normalOrder = implicitly[Ordering[(Int, String)]]
val reversedOrder = Ordering.reverse(normalOrder)
val pq = scala.collection.mutable.PriorityQueue[(Int, String)](reversedOrder)

In Scala, how to get a slice of a list from nth element to the end of the list without knowing the length?

I'm looking for an elegant way to get a slice of a list from element n onwards without having to specify the length of the list. Lets say we have a multiline string which I split into lines and then want to get a list of all lines from line 3 onwards:
string.split("\n").slice(3,X) // But I don't know what X is...
What I'm really interested in here is whether there's a way to get hold of a reference of the list returned by the split call so that its length can be substituted into X at the time of the slice call, kind of like a fancy _ (in which case it would read as slice(3,_.length)) ? In python one doesn't need to specify the last element of the slice.
Of course I could solve this by using a temp variable after the split, or creating a helper function with a nice syntax, but I'm just curious.
Just drop first n elements you don't need:
List(1,2,3,4).drop(2)
res0: List[Int] = List(3, 4)
or in your case:
string.split("\n").drop(2)
There is also paired method .take(n) that do the opposite thing, you can think of it as .slice(0,n).
In case you need both parts, use .splitAt:
val (left, right) = List(1,2,3,4).splitAt(2)
left: List[Int] = List(1, 2)
right: List[Int] = List(3, 4)
The right answer is takeRight(n):
"communism is sharing => resource saver".takeRight(3)
//> res0: String = ver
You can use scala's list method 'takeRight',This will not throw exception when List's length is not enough, Like this:
val t = List(1,2,3,4,5);
t.takeRight(3);
res1: List[Int] = List(3,4,5)
If list is not longer than you want take, this will not throw Exception:
val t = List(4,5);
t.takeRight(3);
res1: List[Int] = List(4,5)
get last 2 elements:
List(1,2,3,4,5).reverseIterator.take(2)

Representing a graph (adjacency list) with HashMap[Int, Vector[Int]] (Scala)?

I was wondering how (if possible) I can go about making an adjacency list representation of a (mutable) graph via HashMap[Int, Vector[Int]]. HashMap would be mutable of course.
Currently I have it set as HashMap[Int, ArrayBuffer[Int]], but the fact that I can change each cell in the ArrayBuffer makes me uncomfortable, even though I'm fairly certain I'm not doing that. I would use a ListBuffer[Int] but I would like fast random access to neighbors due to my need to do fast random walks on the graphs. A Vector[Int] would solve this problem, but is there anyway to do this?
To my knowledge (tried this in the REPL), this won't work:
scala> val x = new mutable.HashMap[Int, Vector[Int]]
x: scala.collection.mutable.HashMap[Int,Vector[Int]] = Map()
scala> x(3) = Vector(1)
scala> x(3) += 4 // DOES NOT WORK
I need to be able to both append to it at any time and also access any element within it randomly (given the index). Is this possible?
Thanks!
-kstruct
Using the Vector:
x += 3 -> (x(3) :+ 4) //x.type = Map(3 -> Vector(1, 4))
You might notice that this will fail if there's no existing key, so you might like to set up your map as
val x = new mutable.HashMap[Int, Vector[Int]] withDefaultValue Vector.empty