道歉:我很不错
我有一个项目类
class item(ind:Int,freq:Int,gap:Int){}
我有一个有序的整体列表
val listVar = a.toList
其中a是数组
我想要一个名为metrics的项目列表
ind是(唯一的)整数 freq是ind出现在列表中的次数 缺口是ind与之前列表中的数字之间的最小差距 到目前为止我有:
def metrics = for {
n <- 0 until 255
listVar filter (x == n) count > 0
}
yield new item(n, (listVar filter == n).count,0)
这是废话,我知道 - 任何线索?
答案 0 :(得分:4)
嗯,其中一些很容易:
val freqMap = listVar groupBy identity mapValues (_.size)
这会为您提供ind
和freq
。要获得gap
,我会使用折叠:
val gapMap = listVar.sliding(2).foldLeft(Map[Int, Int]()) {
case (map, List(prev, ind)) =>
map + (ind -> (map.getOrElse(ind, Int.MaxValue) min ind - prev))
}
现在你只需要统一它们:
freqMap.keys.map( k => new item(k, freqMap(k), gapMap.getOrElse(k, 0)) )
答案 1 :(得分:2)
理想情况下,您只想遍历列表一次,并且在每个不同的Int的过程中,您希望增加一个计数器(频率)以及跟踪最小间隙。
您可以使用 case 类来存储频率和最小间隙,存储的值将是不可变的。请注意,可能未定义minGap。
case class Metric(frequency: Int, minGap: Option[Int])
在一般情况下,您可以使用Map[Int, Metric]
查找Metric
不可变对象。寻找最小差距是更难的部分。要查找差距,您可以使用sliding(2)
方法。它将使用大小为2的滑动窗口遍历列表,允许将每个Int与其先前的值进行比较,以便您可以计算间隙。
最后,您需要在遍历列表时累积和更新信息。这可以通过将列表的每个元素折叠到临时结果中来完成,直到遍历整个列表并获得完整的结果。
把事情放在一起:
listVar.sliding(2).foldLeft(
Map[Int, Metric]().withDefaultValue(Metric(0, None))
) {
case (map, List(a, b)) =>
val metric = map(b)
val newGap = metric.minGap match {
case None => math.abs(b - a)
case Some(gap) => math.min(gap, math.abs(b - a))
}
val newMetric = Metric(metric.frequency + 1, Some(newGap))
map + (b -> newMetric)
case (map, List(a)) =>
map + (a -> Metric(1, None))
case (map, _) =>
map
}
listVar的结果:List [Int] = List(2,2,4,4,0,2,2,4,4)
scala.collection.immutable.Map[Int,Metric] = Map(2 -> Metric(4,Some(0)),
4 -> Metric(4,Some(0)), 0 -> Metric(1,Some(4)))
然后,您可以使用map.toSeq.map((i, m) => new Item(i, m.frequency, m.minGap.getOrElse(-1)))
将结果转换为所需的项目类。
您也可以在此过程中直接创建Item对象,但我认为代码更难以阅读。