Eduardo
Eduardo

Reputation: 8392

Building an immutable List based on conditions

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.

EDIT

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

Answers (4)

Shrey
Shrey

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

Samuel Tardieu
Samuel Tardieu

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

pr1001
pr1001

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

Jakozaur
Jakozaur

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

Related Questions