如何使用新值填充对象列表

时间:2011-12-01 14:46:24

标签: scala

道歉:我很不错

我有一个项目类

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)

这是废话,我知道 - 任何线索?

2 个答案:

答案 0 :(得分:4)

嗯,其中一些很容易:

val freqMap = listVar groupBy identity mapValues (_.size)

这会为您提供indfreq。要获得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对象,但我认为代码更难以阅读。