Reputation: 53916
I'm counting the number of urls within a list. To accomplish this I'm adding to a map where the key is the url and the value is the current counter. Each time I encounter the same key, I increment the counter. Here is the code :
var m = new HashMap[String, Int]
for(l <- MyList){
val url = l.getUrl()
var currentCount : Option[Int] = m.get(url)
currentCount match {
case Some(value) =>
var currentCount = value + 1
m = m ++ Map(url -> currentCount)
case None =>
m = m ++ Map(url -> 1)
}
}
I started with an immutable map but found I needed to reassign the map each time in order to maintain the counter values with the associated keys. Is there a solution to use an immutable map accomplish same task as above ?
Upvotes: 1
Views: 628
Reputation: 36
create another map which would be mutable. and append it with the other map to get the new mutable map. e.g
val updatedMap = new HashMap[String, List[Employee]]
val merged = list.groupBy(_._1).map { case (k, v) => k -> v.map(_._2) }
val newMap = updatedMap ++ merged
Upvotes: 0
Reputation: 236
Using only immutable map:
MyList.foldLeft(Map() : Map[String, Int]) { (map, elem) =>
val key = elem.getUrl
map + (key -> (map.getOrElse(key, 0) + 1))
}
Upvotes: 0
Reputation: 10904
The mutable Map approach you have chosen ist quite suitable to the given tasks and should surpass most immutable implementations in used space and time. You should stick to it.
It would be good style to keep the mutability local:
def calculateMap(myList : List[ URL? ]) : immutable.Map[String,Int] = {
var m = new scala.collection.mutable.HashMap[String, Int]
for{
l <- myList
url = l.getUrl()
}{
val currentCount = m.get(url) getOrElse 0
m += (url -> currentCount + 1)
}
Map() ++ m // this transforms m in an immutable map
}
Alternatively if you want to improve speed and the getUrl() method would block you can try to calculate the results in parallel and convert them to a map like this:
def calculateMapPar(myList : IndexedSeq[ URL? ]) : Map[String,Int] =
myList.par.map(url => url.getUrl).groupBy(x => x).mapValues(_.size).seq
Upvotes: 1
Reputation: 7848
You could do something like:
MyList.groupBy(_.getUrl).map(i => (i._1, i._2.size))
That should give you am immutable Map
, grouped by getUrl
which contains the number of times getUrl
was found.
Or, with type signatures for clarity:
val grouped Map[String, List[MyList]] = MyList.groupBy(_.getUrl)
grouped.map( i => (i._1, i._2.size)
What is happening is that the groupBy
will group the list into a map whose key is getUrl
and whose value is a List[MyList]
where each item's getUrl
is equal to the key.
The next line will just transform the Map[String, List[MyList]]
into a Map[String, Int]
by returning the key and the size of the list. The structure of a map is generally the same as a (key, value) tuple - so in the map, you can access the key and values accordingly.
Upvotes: 3