I have the following use case. User is providing two kinds of strings type
and growth
I need to convert the value of each into an integer from a known map and return the sum of both value.
What I did to map the strings is:
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"
}
Now consider user is calling sum("type1", "growth2")
the expected output is 15 because 5 10=15
I wrote this skeleton function but I'm having trouble utilizing the enumeration objects. How can I do this without having so many if/else
?
def sum(type: String, growth: String) : Int = {
var sum:Int = 0
????
return sum
}
if my approach is flawed I'm happy to try another
CodePudding user response:
scala.Enumeration
doesn't let you use syntax like this
object MyEnum extends Enumeration {
val value = "string"
}
It actually requires you to do something more like
object MyEnum extends Enumeration {
val value = Value("string")
}
and then you are passing not String
but MyEnum.Value
.
Since you are giving up on passing around String
s (at least in Scala 2, in Scala 3 you have an option to use type MyEnum = "value1" | "value2"
and/or opaque type MyEnum
), you create a sealed hierarchy instead
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
If you needed to construct a collection of all possible values, instead of scala.Enumeration
you can use Enumeratum library instead
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
CodePudding user response:
This can be done by create a Map
that gives the score for each String
:
val scoreMap = Map(
"type1" -> 5,
"type2" -> 6,
"growth1" -> 1,
"growth2" -> 10,
)
The score can then be computed using foldLeft
:
def score(strings: List[String]) =
strings.foldLeft(0){ case (sum, str) => sum scoreMap.getOrElse(str, 0) }
score(List("type1", "growth2")) // 15
Values that are missing from the Map
have the default value 0
.
CodePudding user response:
You can extend the class Val
of Enumeration
class.
Example:
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
If you wish to use the operator and reuse the val names :
object Types extends Enumeration {
final case class Pairing (value: Int) extends Val (value) {
def (g: Growth): Int = id g.id
}
val type1 = Pairing (5)
val type2 = Pairing (6)
}
object Growths extends Enumeration {
final case class Pairing (value: Int) extends Val (value) {
def (t: Type): Int = t.id id
}
val growth1 = Pairing (1)
val growth2 = Pairing (10)
}
type Type = Types.Pairing
type Growth = Growths.Pairing
// usage:
import Types._
import Growths._
println (type1 growth2) // => 15
println (growth1 type2) // => 7
println (growth1) // => "growth1"