Как мне заполнить список объектов новыми значениями - PullRequest
3 голосов
/ 01 декабря 2011

Извинения: я хорошо noob

У меня есть класс предметов

class item(ind:Int,freq:Int,gap:Int){}

У меня есть упорядоченный список целых чисел

val listVar = a.toList

, где a являетсямассив

Я хочу список элементов, называемых метриками, где

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 ]

4 голосов
/ 01 декабря 2011

Ну, некоторые из них легко:

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)) )
2 голосов
/ 01 декабря 2011

В идеале вы хотите пройти по списку только один раз и в ходе каждого отдельного Int, вы хотите увеличить счетчик (частоту), а также отслеживать минимальный разрыв.

Вы можете использовать класс case для хранения частоты и минимального разрыва, сохраненное значение будет неизменным. Обратите внимание, что minGap не может быть определен.

case class Metric(frequency: Int, minGap: Option[Int])

В общем случае вы можете использовать Map[Int, Metric] для поиска Metric неизменяемого объекта. Поиск минимального зазора является более сложной частью. Чтобы найти пробел, вы можете использовать метод sliding(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, 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, но я думал, что код будет сложнее читать.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...