2014-01-14 22 views
3

要在scala中使用番石榴TableMultiset?在scala中是否有不同的concenpts,而不是爲了這個用途而導入guava庫?有番石榴MultiSet和表概念的Scala替代品嗎?

+0

我想你可以使用'地圖,而不是'表'和''代替多重集''地圖[T,INT] [(R,C),V]'。 – senia

+0

我看不到我可以做Map [T,Int] .add(「mykey」),然後是Map [T,Int] .size(「mykey」),它會返回我添加的項目數類型'T' – Jas

+0

'add'的代碼示例太大而無法評論。作爲回答添加。 – senia

回答

5

您可以使用Map[(R, C), V]而不是Table<R, C, V>Map[T, Int]而不是Multiset<T>。你也可以添加輔助方法Map[T, Int]這樣的:

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 
+0

如果我們想要併發然後到'def setAdd(e:T,i:Int = 1)= {val cnt = m.getOrElse(e,0)+ i',如果我們想要增加併發性併發......這並不意味着我們正在重新實施番石榴ConcurrentMultiset? – Jas

+0

@Jas:在不同的線程中共享可變集合 - 我不認爲這是一個scala方法。 – senia

+0

@Jas:注意這個實現是不可變的。 – senia

1

這是使用Map[(R, C), V]作爲委託收集第一天真的實現。 rowscolumns被用作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) 
    } 

} 
+0

你好。請不要將代碼轉儲爲答案,請解釋您的思路,以便用戶瞭解正在發生的事情。乾杯! – Cthulhu

+0

這是使用'Map [(R,C),V]'作爲委託集合的番石榴Table接口的實現。 –