Reputation: 8392
I have to build a list whose members should be included or not based on a different condition for each.
Let's say I have to validate a purchase order and, depending on the price, I have to notify a number of people: if the price is more than 10, the supervisor has to be notified. If the price is more than 100 then both the supervisor and the manager. If the price is more than 1000 then the supervisor, the manager, and the director.
My function should take a price as input and output a list of people to notify. I came up with the following:
def whoToNotify(price:Int) = {
addIf(price>1000, "director",
addIf(price>100, "manager",
addIf(price>10, "supervisor", Nil)
)
)
}
def addIf[A](condition:Boolean, elem:A, list:List[A]) = {
if(condition) elem :: list else list
}
Are there better ways to do this in plain Scala? Am I reinventing some wheel here with my addIf
function?
Please note that the check on price is just a simplification. In real life, the checks would be more complex, on a number of database fields, and including someone in the organizational hierarchy will not imply including all the people below, so truncate-a-list solutions won't work.
Basically, I want to achieve the following, using immutable lists:
def whoToNotify(po:PurchaseOrder) = {
val people = scala.collection.mutable.Buffer[String]()
if(directorCondition(po)) people += "director"
if(managerCondition(po)) people += "manager"
if(supervisorCondition(po)) people += "supervisor"
people.toList
}
Upvotes: 8
Views: 828
Reputation: 2404
Well, its a matter of style, but I would do it this way to make all the conditions more amenable -
case class Condition(price: Int, designation: String)
val list = List(
Condition(10, "supervisor"),
Condition(100, "manager") ,
Condition(1000, "director")
)
def whoToNotify(price: Int) = {
list.filter(_.price <= price).map(_.designation)
}
You can accommodate all your conditions in Condition class
and filter
function as per your requirements.
Upvotes: 3
Reputation: 2081
You can use List#flatten()
to build a list from subelements. It would even let you add two people at the same time (I'll do that for the managers in the example below):
def whoToNotify(price:Int) =
List(if (price > 1000) List("director") else Nil,
if (price > 100) List("manager1", "manager2") else Nil,
if (price > 10) List("supervisor") else Nil).flatten
Upvotes: 4
Reputation: 21962
If you have an original list of members, you would probably want to consider using the filter
method. If you also want to transform the member object so as to have a different type of list at the end, take a look at the collect
method, which takes a partial function.
Upvotes: 1
Reputation: 1977
Well, it is a matter of style, but I would prefer keeping a list of people to notify with rules rather than function nesting. I don't see much value in having something like addIf
in above example.
My solution.
val notifyAbovePrice = List(
(10, "supervisor"),
(100, "manager"),
(1000, "director"))
def whoToNotify(price: Int): Seq[String] = {
notifyAbovePrice.takeWhile(price > _._1).map(_._2)
}
In real world, you may have objects to notifyAbovePrice
instead of tuples and use filter
instead of takeWhile
if there is no order or the order doesn't imply notifications on lower level.
Upvotes: 2