根据条件构建不可变列表

时间:2013-01-20 12:25:04

标签: scala

我必须建立一个列表,其成员应该包含或不基于每个成员的不同条件。

假设我必须验证采购订单,并且根据价格,我必须通知许多人:如果价格超过10,则必须通知主管。如果价格超过100,那么主管和经理。如果价格超过1000,那么主管,经理和主管。

我的功能应该以价格作为输入并输出要通知的人员列表。我想出了以下内容:

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
}

在Scala中有更好的方法吗?我用我的addIf功能重新发明了一些轮子吗?

请注意,价格检查只是一种简化。在现实生活中,检查在许多数据库字段中会更复杂,并且组织层次结构中的某些人不会暗示包括下面的所有人,因此截断列表解决方案将无法工作。

修改

基本上,我想使用不可变列表来实现以下目的:

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
}

4 个答案:

答案 0 :(得分:4)

您可以使用List#flatten()从子元素构建列表。它甚至可以让你同时添加两个人(我将在下面的例子中为经理做这些):

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

答案 1 :(得分:3)

嗯,这是一个风格问题,但我会这样做,以使所有条件更合适 -

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)
}     

您可以根据自己的要求在Condition classfilter功能中满足您的所有条件。

答案 2 :(得分:2)

嗯,这是一个风格问题,但我更希望保留一个人员列表来通知规则而不是功能嵌套。在上面的示例中,我没有看到像addIf这样的内容有多大价值。

我的解决方案。

val notifyAbovePrice = List(
    (10, "supervisor"),
    (100, "manager"),
    (1000, "director"))

def whoToNotify(price: Int): Seq[String] = {
  notifyAbovePrice.takeWhile(price > _._1).map(_._2)
}

在现实世界中,如果没有订单或订单不暗示较低级别的通知,那么您可能有notifyAbovePrice而不是元组的对象而使用filter代替takeWhile

答案 3 :(得分:1)

如果您有原始成员列表,则可能需要考虑使用filter方法。如果您还想转换成员对象以便在最后使用不同类型的列表,请查看collect方法,该方法具有部分功能。