如何在Scala中将多个字符串Map为整数值?

f45qwnt8  于 2023-01-17  发布在  Scala
关注(0)|答案(3)|浏览(112)

我有以下用例。用户提供两种字符串typegrowth。我需要将每个字符串的值转换为已知Map中的整数,并返回两个值的总和。
我Map字符串的方法是:

object Types extends Enumeration {

  val T1 = 5
  val T2 = 6
  // list of values is really long!

  val TYPE1 = "type1"
  val TYPE2 = "type2"
}

object Growth extends Enumeration {

  val G1 = 1
  val G2 = 10
  // list of values is really long!

  val GROWTH1 = "growth1"
  val GROWTH2 = "growth2"
}

现在假设用户正在调用sum("type1", "growth2"),预期输出为15,因为5+10=15
我写了这个 backbone 函数,但是我在使用枚举对象时遇到了麻烦。如果没有这么多的if/else,我该怎么做呢?

def sum(type: String, growth: String) : Int = {
      var sum:Int = 0
      ????
      return sum
   }

如果我的方法有缺陷,我很乐意尝试另一种方法

fnvucqvd

fnvucqvd1#

scala.Enumeration不允许使用这样的语法

object MyEnum extends Enumeration { 
  val value = "string"
}

它实际上要求你做一些更像

object MyEnum extends Enumeration {
  val value = Value("string")
}

然后你传递的不是String而是MyEnum.Value
由于放弃了传递String(至少在Scala 2中,在Scala 3中可以选择使用type MyEnum = "value1" | "value2"和/或opaque type MyEnum),因此创建了一个密封层次结构

sealed abstract class Type(
  val name: String,
  val number: Int
) extends Product with Serializable
object Type {
  case object Type1 extends Type("type1", 5)
  case object Type2 extends Type("type2", 6)
}

sealed abstract class Growth(
  val name: String,
  val number: Int
) extends Product with Serializable
object Growth {
  case object Growth1 extends Growth("growth1", 1)
  case object Growth2 extends Growth("growth2", 10)
}

def sum(`type`: Type, growth: Growth) : Int =
  `type`.number + growth.number

如果需要构造所有可能值的集合,可以使用Enumeratum库代替scala.Enumeration

import enumeratum.values._

// IntEnumEntry and IntEnum specialize for Int
// and it allows to eliminate boxing

// The Int has to be defined as `val value: Int`

// findValues has to called so that the compiler
// can find all instances in the compile-time and
// populate the `values` collection

// Enumeratum then generate a lot of useful methods out of
// this list e.g. `withName` to find enum by its name

sealed abstract class Type(
  val value: Int
) extends IntEnumEntry
object Type extends IntEnum[Type] {
  case object Type1 extends Type(5)
  case object Type2 extends Type(6)

  val values = findValues
}

sealed abstract class Growth(
  val value: Int
) extends IntEnumEntry
object Growth extends IntEnum[Growth] {
  case object Growth1 extends Growth(1)
  case object Growth2 extends Growth(10)

  val values = findValues
}

def sum(`type`: Type, growth: Growth) : Int =
  `type`.value + growth.value
uqxowvwt

uqxowvwt2#

这可以通过创建一个Map来完成,该Map给出每个String的分数:

val scoreMap = Map(
  "type1" -> 5,
  "type2" -> 6,
  "growth1" -> 1,
  "growth2" -> 10,
)

然后可以使用foldLeft计算得分:

def score(strings: List[String]) =
    strings.foldLeft(0){ case (sum, str) => sum + scoreMap.getOrElse(str, 0) }

score(List("type1", "growth2")) // 15

Map中缺少的值具有默认值0

slsn1g29

slsn1g293#

可以扩展Enumeration类的Val类。
示例:

object Types extends Enumeration {
    final case class Pairing (label: String, value: Int) extends Val (value, label)

    val TYPE1 = Pairing ("type1", 5)
    val TYPE2 = Pairing ("type2", 6)
}

object Growths extends Enumeration {
    final case class Pairing (label: String, value: Int) extends Val (value, label)

    val GROWTH1 = Pairing ("growth1", 1)
    val GROWTH2 = Pairing ("growth2", 10)
}

type Type = Types.Pairing
type Growth = Growths.Pairing

def sum (t: Type, g: Growth): Int = t.id + g.id

// usage:
import Types._
import Growths._

println(sum(TYPE1, GROWTH2)) // => 15

相关问题