Frage

To use guava Table and Multiset in scala? are there already different concenpts in scala instead of importing guava library for this usage?

War es hilfreich?

Lösung

You could use Map[(R, C), V] instead of Table<R, C, V> and Map[T, Int] instead of Multiset<T>. You could also add helper methods to Map[T, Int] like this:

implicit class Multiset[T](val m: Map[T, Int]) extends AnyVal {
  def setAdd(e: T, i: Int = 1) = {
    val cnt = m.getOrElse(e, 0) + i
    if (cnt <= 0) m - e
    else m.updated(e, cnt)
  }
  def setRemove(e: T, i: Int = 1) = setAdd(e, -i)
  def count(e: T) = m.getOrElse(e, 0)
}

val m = Map('a -> 5)

m setAdd 'a
// Map('a -> 6)

m setAdd 'b
// Map('a -> 5, 'b -> 1)

m setAdd ('b, 10)
// Map('a -> 5, 'b -> 10)

m setRemove 'a
// Map('a -> 4)

m setRemove ('a, 6)
// Map()

m count 'b
// 0

(m setAdd 'a) count 'a
// 6

Andere Tipps

This is a first naive implementation using Map[(R, C), V] as a delegated collection. rowsand columns are used as indexes for the m: Map.

package utils.collections

import utils.collections.Table.Cell

class Table[R, C, V](val m: Map[(R, C), V], val rows: Map[R, List[(R, C)]], val columns: Map[C, List[(R, C)]]) {

  def containsValue(value: V): Boolean = m.values.exists(_.equals(value))

  def values(): List[V] = m.values.toList

  def get(rowKey: R, columnKey: C): Option[V] = m.get(rowKey, columnKey)

  def apply(rowKey: R, columnKey: C): V = m.apply((rowKey, columnKey))

  def cellSet(): Set[Cell[R, C, V]] = m.map { case ((r, c), v) => Cell(r, c, v) }.toSet

  def contains(rowKey: R, columnKey: C): Boolean = m.contains((rowKey, columnKey))

  def put(rowKey: R, columnKey: C, value: V): Table[R, C, V] = {
    val keys: (R, C) = (rowKey, columnKey)
    new Table(
      m = m + ((keys, value)),
      rows = rows + ((rowKey, keys::rows.getOrElse(rowKey, List.empty))),
      columns = columns + ((columnKey, keys::columns.getOrElse(columnKey, List.empty)))
    )
  }

  def putAll(table: Table[_ <: R, _ <: C, _ <: V]): Table[R, C, V] = Table(m.++(xs = table.m))

  def remove(rowKey: R, columnKey: C): Table[R, C, V] = {
    val keys: (R, C) = (rowKey, columnKey)
    val updatedRows: Map[R, List[(R, C)]] = rows.get(rowKey) match {
      case Some(keysWithRow) if keysWithRow.diff(List(keys)).nonEmpty => rows + ((rowKey, keysWithRow.diff(List(keys))))
      case _ => rows - rowKey
    }
    val updatedColumns: Map[C, List[(R, C)]] = columns.get(columnKey) match {
      case Some(keysWithColumn) if keysWithColumn.diff(List(keys)).nonEmpty => columns + ((columnKey, keysWithColumn.diff(List(keys))))
      case _ => columns - columnKey
    }
    new Table(
      m = m - keys,
      rows = updatedRows,
      columns = updatedColumns
    )
  }

  def row(rowKey: R): Map[C, V] = m.filterKeys(k => rows.get(rowKey).exists(_.equals(k))).map { case ((_, c), v) => (c, v) }

  def containsRow(rowKey: R): Boolean = rows.exists(_.equals(rowKey))

  def rowMap(): Map[R, Map[C, V]] = m.groupBy { case ((r, _), _) => r }.map { case (r, subMap) => (r, subMap.map { case ((_, c), v) => (c, v) }) }

  def rowKeySet(): Set[R] = rows.keySet

  def column(columnKey: C): Map[R, V] = m.filterKeys(k => columns.get(columnKey).exists(_.equals(k))).map { case ((r, _), v) => (r, v) }

  def containsColumn(columnKey: C): Boolean = columns.exists(_.equals(columnKey))

  def columnMap(): Map[C, Map[R, V]] = m.groupBy { case ((_, c), _) => c }.map { case (c, subMap) => (c, subMap.map { case ((r, _), v) => (r, v) }) }

  def columnKeySet(): Set[C] = columns.keySet

  def size(): Int = m.size

  def isEmpty: Boolean = m.isEmpty

}

object Table {

  case class Cell[R, C, V](rowKey: R, columnKey: C, value: V)

  def empty[R, C, V] = new Table[R, C, V](Map.empty, Map.empty, Map.empty)

  def apply[R, C, V](m: Map[(R, C), V]): Table[R, C, V] = {
    val rows: Map[R, List[(R, C)]] = m.keys.groupBy { case (r, c) => r }.map { case (r, keys) => r -> keys.toList }
    val columns: Map[C, List[(R, C)]] = m.keys.groupBy { case (r, c) => c }.map { case (c, keys) => c -> keys.toList }
    new Table[R, C, V](m, rows, columns)
  }

}
Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top