【问题标题】:Efficient map with case class as a key in Scala?以案例类为键的高效映射在 Scala 中?
【发布时间】:2011-06-17 01:09:54
【问题描述】:

以下 C 代码使用枚举和数组作为从枚举到任何事物的高效“映射”:

enum Color { ColorRed, ColorGreen, ColorBlue, ColorSize};


void f() {
  int x[ColorSize];
  x[ColorRed]   = 12;
  x[ColorGreen] = 33;
  x[ColorBlue]  = 4;
  return x[ColorGreen];
}

Scala 可以做到这一点吗?
IE。有一个从案例类到某物的“映射”,实现为高效数组而不是树或哈希图。然而,我希望能够仅使用特定类型而不是 Int 进行索引。

更新:简而言之,我希望 Scala 数组由某种枚举(案例类或枚举)索引。

【问题讨论】:

  • 我想我对术语感到困惑。你想要一个数组,但它是由 enum 而不是 int 索引的?
  • 数组总是由整数索引。如果它被对象索引,那么它就是某种哈希表。
  • @Synesso:你是对的。我更新了问题。
  • @Synesso 我的评论是针对@Łukasz Lew

标签: scala scala-2.8 case-class


【解决方案1】:

对于小型枚举,您可以“模拟”C 行为:

abstract sealed class Color(val index: Int)

object Color {
  implicit def col2int(color:Color) = color.index
}

case object ColorRed extends Color(0)
case object ColorGreen extends Color(1)
case object ColorBlue extends Color(2)

...

import Color._
val array = Array(1,2,3)
array(ColorRed) = 12

但是,我怀疑这会被认为是好的风格,尤其是因为它不安全。使用地图是一种更好的方法,或者您可以将数组包装在处理颜色索引的专用数据结构中:

class ColorArray[T:ClassManifest] {
  val array = new Array[T] (3)
  def apply(color: Color) = array(color.index)
  def update(color: Color, value: T) = array(color.index) = value
}

...

val cArray = new ColorArray[Int]()
cArray(ColorRed) = 12
println(cArray(ColorRed))

【讨论】:

  • 注意这里可以写abstract class Colorcase object ColorX。此外,您的数组访问返回值与其声明不匹配。
  • 按照建议更正了颜色定义。我不太明白你的第二句话。
  • 对不起,我的错。有没有办法找出运行时存在多少 Color 的情况?然后你必须对数组大小进行硬编码。你可以用 Java 的枚举来做到这一点。
  • 对于第二个解决方案,为什么不包括到常规数组(或Seq 或其他)的隐式转换以获得所有好的方法?为了完整起见,object ColorArray 也应该被实现。
  • 第二种解决方案适用于 case 对象和 Scala 枚举键,在第二种情况下,您可以自动获取数组长度。当然你可以添加隐式转换,但是数组不是私有的,所以你可以简单地调用 cArray.array 和 have 所有不错的方法。这实际上取决于您想要实现的目标。根据您的需要,您有很多可能性,或多或少的便利性,或多或少的类型安全性和或多或少的性能。
【解决方案2】:
对象颜色扩展枚举{ val ColorRed、ColorGreen、ColorBlue = 值 } 导入颜色._ def f:Map[Color.Value,Int] = 地图(红色 -> 12 ,绿色 -> 33,蓝色 -> 4)

【讨论】:

  • 这和数组查找一样高效吗?
  • 默认的 Map 实现是一个哈希映射,它提供了非常快速的查找。
【解决方案3】:

如果您想要完整的 C 性能,您可以这样做:

trait CEnum {
private var size = 0;
def value = { size += 1; size-1 }
}

object Color extends CEnum {
  val colorRed = value 
  val colorGreen = value 
  val colorBlue = value 
  val colorSize = 3
}

import Color._

def f() = {
  val x = Array[Int](colorSize)
  x(colorRed) = 12
  x(colorGreen) = 33
  x(colorBlue) = 4
  x(colorGreen)
}

它与 C 中的方法同样不安全,而且性能同样出色。然而它非常不安全。

【讨论】:

    猜你喜欢
    • 2010-11-16
    • 2021-10-12
    • 1970-01-01
    • 1970-01-01
    • 2011-09-26
    • 1970-01-01
    • 2011-11-12
    • 1970-01-01
    相关资源
    最近更新 更多