7

我必须根据每个不同的条件建立一个列表,其成员应该包括或不包括在内。

假设我必须验证采购订单,并且根据价格,我必须通知一些人:如果价格超过 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

4 回答 4

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
于 2013-01-20T12:49:17.640 回答
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 class并发挥作用。filter

于 2013-01-20T13:13:21.107 回答
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

于 2013-01-20T12:38:36.930 回答
1

如果您有原始成员列表,您可能会考虑使用该filter方法。如果您还想转换成员对象以在末尾具有不同类型的列表,请查看该collect方法,该方法采用偏函数。

于 2013-01-20T12:40:04.687 回答