我正在计算列表中的网址数量。 为了实现这一点,我将添加到一个地图,其中键是url,值是当前计数器。每次遇到相同的密钥时,我都会递增计数器。这是代码:
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)
}
}
我从一个不可变的地图开始,但发现每次都需要重新分配地图,以便用相关的键维护计数器值。是否存在使用不可变映射完成上述相同任务的解决方案?
答案 0 :(得分:3)
您可以执行以下操作:
MyList.groupBy(_.getUrl).map(i => (i._1, i._2.size))
这应该是一个不可变的Map
,按getUrl
分组,其中包含找到getUrl
的次数。
或者,为清晰起见,使用类型签名:
val grouped Map[String, List[MyList]] = MyList.groupBy(_.getUrl)
grouped.map( i => (i._1, i._2.size)
正在发生的事情是groupBy
会将列表分组到一个地图,其关键字为getUrl
,其值为List[MyList]
,其中每个项目的getUrl
等于关键。
下一行只会返回密钥和列表大小,将Map[String, List[MyList]]
转换为Map[String, Int]
。地图的结构通常与(键,值)元组相同 - 因此在地图中,您可以相应地访问键和值。
答案 1 :(得分:1)
您选择的可变Map方法非常适合给定的任务,并且应该超越使用空间和时间中的大多数不可变实现。 你应该坚持下去。
保持本地可变性是一种很好的风格:
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
}
或者,如果您想提高速度并且getUrl()方法会阻止,您可以尝试并行计算结果并将它们转换为这样的地图:
def calculateMapPar(myList : IndexedSeq[ URL? ]) : Map[String,Int] =
myList.par.map(url => url.getUrl).groupBy(x => x).mapValues(_.size).seq
答案 2 :(得分:0)
仅使用不可变地图:
MyList.foldLeft(Map() : Map[String, Int]) { (map, elem) =>
val key = elem.getUrl
map + (key -> (map.getOrElse(key, 0) + 1))
}
答案 3 :(得分:0)
创建另一个可变的地图。并附加其他地图以获得新的可变地图。 例如
pageToken