How do you get and remove an arbitrary element from a mutable HashSet in Scala (similar to python set pop method)? Also what would be the performance of the api?
For extracting and removing elements in undefined order from a mutable hash set, try a combination of head and -= (remove):
import scala.collection.mutable.HashSet
def pop[A](hs: HashSet[A]): A = {
val a = hs.head
hs -= a
a
}
val example = HashSet.empty[Int] ++ (0 to 9)
while (!example.isEmpty) {
val p = pop(example)
println("Pop element: " + p)
}
I'm not sure whether it's caching any keys or hashes internally, but afaik it's either just O(1) or amortized O(1).
#Andrey's answer above should suffice to answer your question as he said
you can use .head function to pop an element.
Here are some more details.
Sets are one of the collection libraries of Scala which provide both mutable and immutable methods. If you want specific element to be removed from Sets then there is - and + methods. - method is used for removing an element from a Set and a new Set is returned. Similarly + method is used for adding an element in a Set which also returns a new Set with the element added. So you can write pop and set functions that will remove and add specific elements.
def popFromSet[T](set: Set[T], stringToPop: T) = {
set - stringToPop
}
def setToSet[T](set: Set[T], stringToPop: T) = {
set + stringToPop
}
And you can use them as
popFromSet(stringSet, "second")
setToSet(popFromSet(stringSet, "second"), "second2")
popFromSet(intSet, 2)
....
List way
You can do the above Set to List
If you have a HashSet as
Set("first", "second", "third")
You can get the second element popped out by doing
val hashList = hashSet.toList
hashList(hashList.indexOf("second"))
and if you want to remove the second element from the HashSet then
hashSet - hashList(hashList.indexOf("second"))
I hope the answer is helpful
Related
How do I get the k-th minimum element of a Priority Queue in Scala?
I tried the following but it seems to be wrong!
import collection.mutable
object Main {
def main(args: Array[String]): Unit = {
val asc = Ordering.by((_: (Double, Vector[Double]))._1).reverse
val pq = mutable.PriorityQueue.empty[(Double, Vector[Double])](asc)
pq.enqueue(12.4 -> Vector(22.0, 3.4))
pq.enqueue(1.2 -> Vector(2.3, 3.2))
pq.enqueue(9.1 -> Vector(12.0, 3.2))
pq.enqueue(32.4 -> Vector(22.0, 13.4))
pq.enqueue(13.2 -> Vector(32.3, 23.2))
pq.enqueue(93.1 -> Vector(12.0, 43.2))
val k = 3
val kthMinimum = pq.take(k).last
println(kthMinimum)
}
}
It's explicitly stated in Scala API doc:
Only the dequeue and dequeueAll methods will return elements in
priority order (while removing elements from the heap). Standard
collection methods including drop, iterator, and toString will remove
or traverse the heap in whichever order seems most convenient.
If you want to stick to using PriorityQueue, it seems dequeue-ing k times or pq.dequeueAll(k-1) might be the only means to achieve priority retrieval.
The problem is the incompatibility between PriorityQueue properties and inherited collection methods like take etc. Another example of weird implementation issues with Scala collections.
Same problems exist with Java's PriorityQueue.
import java.util.PriorityQueue
val pQueue = new PriorityQueue[Integer]
pQueue.add(10)
pQueue.add(20)
pQueue.add(4)
pQueue.add(15)
pQueue.add(9)
val iter = pQueue.iterator()
iter.next() // 4
iter.next() // 9
iter.next() // 10
iter.next() // 20
iter.next() // 15
So, PriorityQueue maintains your data in an underlying ArrayBuffer (not exacltly but an special inherited class). This "Array" is kept heapified. And the inherited take API works on top of this heapified Array-like data structure. And first k elements of a min-heapified Array are certainly not same as minimum k elements.
Now, definition a PriorityQueue is supposed to support enqueue and dequeue. It just maintains the highest priotiry (first) element and is just incapable of reliably providing k-th element in the queue.
Although I say that this is a problem with both Java and Scala implementations, its just not possible to come up with a sane implemention for this. I jsut wonder that why are these misleading methods still present in PriorityQueue implementations. Can't we just remove them ?
I strongly suggest staying with the strictest API suited for your requirement. In other words stick with Queue API and not using the inherited API methods (which might do weird things).
Although, there is no good way of doing it (as it is not something explicitly required for a PriorityQueue).
You can achieve this by simply dequeueing k times in a loop with time complexity of k * log(n).
val kThMinimum = {
val pqc = pq.clone()
(1 until k).foreach(i => pqc.dequeue())
pqc.dequeue()
}
With a background from object-oriented programming I am not able to understand how to make immutable lists in Scala.
Example; I want to make a list of 10 random people:
object MyApplication extends App {
val numberOfPersons = 10 : Int
val listOfPersons = makeListOfPersons(numberOfPersons) : List[Person]
def makeListOfPersons( numberOfPersons : Int ) : List[Person] = {
// TODO: return a immutable list of 10 persons
}
}
class Person {
/**
Generic content,
like age and name.
* */
}
What is the "correct" way of making an immutable list in Scala?
If you know what collection type you want, you may be able to use the tabulate method on that type:
List.tabulate(10)(makePerson)
In this case makePerson is a function that takes an Int and returns the Person object for that Int.
If you don't care about the collection type, you can call map on the range 1 to 10 like this:
(1 to 10).map(makePerson)
If you don't need to use the Int parameter, you can do this:
List.tabulate(10)(_ => makeRandomPerson())
In this particular case,
List.fill(numberOfPersons){ codeThatCreatesASinglePerson }
seems most appropriate.
In most other cases: Nil creates an empty list, x :: y prepends an element x to list y.
If you want to append to list, instead of prepending to it, then you can take a collection.mutable.ListBuffer, append to it all the elements that you want to have in the list, and then call toList when you're done... or just use the built-in factory methods that do exactly that.
As the default List in Scala is immutable, the right way to add an element is to return a new list with the new element plus the older elements.
As a matter of fact, List has two methods, among others:
+:
++
The first one takes an element, add it as the first element and the rest of the list as it's tail and then returns the resulting list.
The other one takes another "collection" as parameter and adds it to the first list at the start.
List has another methods for adding the new element as the last one.
In Scala, these operations are permitted but take into consideration that always a new instance will be retrieved with the requested modifications as all objects are immutable by default.
As for your code goes, you could try with something like this:
object MyApplication extends App {
val numberOfPersons: Int = 10
val listOfPersons: List[Person] = makeListOfPersons(numberOfPersons)
def makeListOfPersons( numberOfPersons : Int ) : List[Person] = {
(1 to numberOfPersons).foldLeft(List.empty[Person]){ (accum, elem) =>
new Person() :: accum
}
}
}
(1 to numberOfPersons) creates a range, which could be seen as a List of ints, which will be traversed by foldLeft. This method will iterate through that list, and receives a seed, in this case an empty list of Person. Then, for every element in the int's list, a new Person is created and add to the list, returned as is the last expression and used the accumulator for the next iteration. Finally, a list of ten instances of Person is retrieved.
There are 5 ways to create List in scala:
Lisp style:
val list = 1::2::3::Nil
this style can also be thought of as a Haskell or functional programming (FP) style.
Java Style:
val list = List(1,2,3)
Scala List with range method
List.range(1, 10)
Create scala List with fill
List.fill(3)(5)
Scala List with tabulate
List.tabulate(5)(n => n * n)
element of the list are created according to the function we supply.
for more info please read this :
Preferred way to create a Scala list
I guess I kinda murdered the title but I could not express it another way.
I have a trait like this:
trait Flaggable[T <: Flaggable[T]] { self : T =>
def setFlag(key: String, value: Boolean): T
def getFlag(key:String): Boolean
}
This trait itself is not that important, but main thing here is class implementing it should be immutable as setFlag returns a new instance. Example class extending this trait:
class ExampleData(val flags: Map[String, Boolean] = Map())
extends Flaggable[ExampleData] {
def setFlag(key: String, value: Boolean): ExampleData =
new ExampleData(flags + (key->value))
def getFlag(key:String): Boolean = flags(key)
}
While iterating over collection I set flags on elements and I want those flags to be effective in subsequent iterations. Something like
val seq: Seq[ExampleData] = ???
seq.view.filter(el => !el.getFlag("visited")).foreach { el =>
// do things that may set flag visited to true in elements
// further in the seq, if that happens I do want those
// elements to be filtered
}
Now AFAIK, one option is to make seq mutable and assign new instances returned from setFlag to seq. Another option is to make whole flaggable thing mutable and modify instances in place in collection. Do I have any other option without making either of these (class and collection) mutable? I do not even know how can I modify and filter at the same time in that case.
I guess I should explain my situation more. Specifically, I am trying to implement dbscan clustering algorithm. I have a function that can return distance between two data points. For each data point, I need to get data points that is closer than an epsilon to that data point and mark those visited. And I do not want to process data points that is marked visited again. For example, for data point with index 0, the index list of data points closer than epsilon might be [2, 4, 5]. In this case I want to flag those data points as visited and skip over them without processing.
Just use map instead of foreach and replace the order of the functions:
seq.view.map { el =>
// do things that may set flag visited to true and return the new
// or e1 if no change needed.
}.filter(el => !el.getFlag("visited"))
Update:
Since the filter and the update related to each other, use mutable collection. I prefer that than mutable data objects, since it can be limit only to that scope. (e.g. use seq.to[ListBuffer]). after you done, all the mutations gone.... This allow keep the mutable code locally.
Nevertheless, depends on your algorithm, there may be a better collection for that, like Zipper.
I think you could extract a function to handle what is done inside your foreach with a signature like:
def transform(in: ExampleData): ExampleData
with that you could use a for comprehension:
for {
elem <- seq if !elem.getFlag("visited")
result = transform(elem) if result.getFlag("Foo")
} yield result
If you have multiple operations you can just append:
for {
elem <- seq if !elem.getFlag("visited")
r1 = transform(elem) if r1.getFlag("Foo")
r2 = transform2(r1) if r2.getFlag("Bar")
} yield r2
The result would be a new Seq of new ExampleData according to the transformations and filters applied.
In general, if you want to both filter and process elements you would usually use the collect function and possibly chain them:
seq.collect {
case elem if !elem.getFlag("visited") => transform(elem)
}.collect {
case elem if elem.getFlag("Foo") => transform2(elem)
}.filter(_.getFlag("Bar")
I have a var permutedTables = HashMap[List[Int], List[String, String]] defined globally. I first populate the Hashmap with the keys in a method, which works.
print(permutedTables) :
Map(List(1,2,3,4) -> List(),
List(2,4,5,6) -> List(), etc...)
The problem occurs when I want to update the values (empty lists) of the HashMap inside a for loop (inside a second method). In other words, I want to add tuples (String, String) in the List() for each key.
for(pi_k <- permutedTables.keySet){
var mask = emptyMask;
mask = pi_k.foldLeft(mask)((s, i) => s.updated(i, '1'))
val maskB = Integer.parseInt(mask,2)
val permutedFP = (intFP & maskB).toBinaryString
// attempt 1 :
// permutedTables(pi_k) :+ (url, permutedFP)
// attempt 2 :
// permutedTables.update(pi_k, permutedTables(pi_k):::List((url, permutedFP)))
}
The values do not update. I still have empty lists as values. I don't understand what is wrong with my code.
EDIT 1: When I call print(permutedTables) after any of the two attempts (inside the loop), the value seem updated, but when I call it outside of the loop, the Lists are empty
EDIT 2: The second attempt in my code seems to work now(!). But why does first not work ?
The second attempt in my code seems to work now(!). But why does first not work ?
Because what you do in the first case is get a list from permutedTables, add an element and throw away the result without storing it back. It would work if you mutated the value, but a List is immutable. With List, you need
permutedTables += pi_k -> permutedTables(pi_k) :+ (url, permutedFP)
Or, as you saw, update.
You can use e.g. ArrayBuffer or ListBuffer as your value type instead (note that you need :+= instead of :+ to mutate them), and convert to your desired type at the end. This is going to be rather more efficient than appending to the end of the list, unless the lists are quite small!
Finally, note that you generally want either var or a mutable type, not both at the same time.
I'm have a map that looks like this: Map[ A -> Collection[B]]. This map gets updated in a loop - the special thing is however, that updates mostly just mean adding an element B to the Collection[B] (for some key A).
I am trying to find out if I can get some speedup by changing the type of my Collection from List[ ] to ListBuffer[ ].
Up to now my code looked like this (simplified):
var incoming = new HashMap[A, List[B]() {
override def default(a: A) = List()
}
..
for(b < someCollectionOfBs){
..
incoming(b.getA) = b :: incoming(b.getA)
..
}
This works fine. Now, I changed the type of the map so it looks like this:
var incoming = new collection.mutable.HashMap[A, ListBuffer[B]() {
override def default(a: A) = collection.mutable.ListBuffer()
}
..
for(b < someCollectionOfBs){
..
incoming(b.getA) += b
..
}
Note the change in how the element B is added to the collection in the 2nd example (no more immutable List, hence we do not need to create and assign new collection...).
But. This does not work: incoming(X) += .. does not update the value of the map for X, actually it does not change anything.
What am I missing here? I thought that I should be able to update the values of a mutable HashMap... So, if my values are mutable collections, why can't I just add elements to those?
The default is returned when the key is not found, but it does not update the map with the default value. You can use getOrElseUpdate for that.
incoming.getOrElseUpdate(b.getA, ListBuffer()) += b
That should do what you want.
Additional note:
If you're concerned about performance, I don't think replacing List with ListBuffer will buy you much, because you are prepending to a List and that should be very fast. ListBuffer is handy when you want to append to a list. You should look at using java.util.HashMap and see if that helps.