【问题标题】:Scala: if inside match caseScala:如果在匹配情况下
【发布时间】:2017-10-28 23:26:20
【问题描述】:

有什么方法可以在 scala 中将 if 放入 match case 中?

类似这样的:

def createSchedules(listTask: List[TaskOrder], physicalResources: List[Physical], humanResources: List[Human], previousTime: Duration): List[TaskSchedule] = listTask match {
    case TaskOrder(id, time, physicalRes, order) :: t =>
      val taskScheduleHumanResources = setHumanResources(physicalRes, humanResources)
      if (physicalRes != null) 
        new TaskSchedule(
          order, 
          order.getProduct(), 
          Task(id, time, physicalRes), 
          physicalRes, 
          taskScheduleHumanResources, 
          order.quantity, 
          previousTime, 
          previousTime + time) :: createSchedules(t, physicalRes, humanResources, previousTime + time)
    case Nil => Nil
  }

这样做我得到一个错误提示:

类型不匹配;找到:所需单元:List[Objects.TaskSchedule]

最好的方法是什么?

【问题讨论】:

  • physicalResnull时你会怎么做?
  • 我没有创建新的任务计划。但我也不能返回 null,否则我会在稍后执行应用程序时收到 nullPointerException。
  • 那么你需要添加一个else Nil。您是否在setHumanResources 中填充physicalRes
  • 不,我不知道。但是您的解决方案有效,它比我想象的要容易。谢谢你。如果你想写一个答案,我可以接受。
  • 请注意,您的代码不是尾递归的,并且会为具有大量元素的listTask 抛出StackOverflowError。养成为所有可疑函数添加@annotation.tailrec 的习惯——这会强制编译器检查必要条件,如果无法实现目标,则编译失败。

标签: scala if-statement functional-programming


【解决方案1】:

编译器推断Unit 的原因是您没有else 子句,这意味着您不会在physicalRes 为空的情况下返回值。

您需要在代码中添加else 子句:

case TaskOrder(id, time, physicalRes, order) :: t => 
  val taskScheduleHumanResources = setHumanResources(physicalRes, humanResources)
  if (physicalRes != null) // stuff
  else createSchedules(t, physicalRes, humanResources, previousTime + time)

您可以使用collect 只选择想要的元素:

val res: List[TaskSchedule] = listTask.collect {
   case order if order.physicalRes != null => new TaskSchedule(...)
}

或者你也可以把集合折叠起来,只有找到非空的时候才累积physicalRes

val res: List[TaskSchedule] = listTask.foldLeft(List.empty[TaskOrder]) {
  case (acc, order) => 
    if (order.physicalRes != null) {
       new TaskSchedule(...) :: acc
    } else acc
}

【讨论】:

  • 您的 foldLeft 解决方案将反转项目的顺序。在这种情况下,这可能很重要,也可能无关紧要,但我认为我应该指出这一点。
  • @JackLeow 原始解决方案已经暗示 OP 不关心订单。
  • 我不知道你是怎么得出这个结论的?你能澄清一下吗?代码似乎保持秩序,他没有说他不关心秩序。
  • @JackLeow 他在递归现有列表时将每个新创建的 TaskSchedule 添加到前面。
  • 你是在暗示他的方法颠倒了列表吗?它不是。仔细阅读代码。我可以为您提供一个示例,您可以根据需要粘贴到 REPL 中。
【解决方案2】:

如果你这样做了

    def createSchedules(listTask: List[TaskOrder],
                        physicalResources: List[Physical],
                        humanResources: List[Human],
                        previousTime: Duration): List[TaskSchedule] = listTask match {
      case TaskOrder(id, time, physicalRes, order) :: t =>{
        val taskScheduleHumanResources = setHumanResources(physicalRes, humanResources);
        if(physicalRes != null) 
          new TaskSchedule(order, order.getProduct(), Task(id, time, physicalRes), physicalRes, taskScheduleHumanResources, order.quantity, previousTime, previousTime + time):: createSchedules(t, physicalRes, humanResources, previousTime + time)
        else 
          Nil
      }
      case Nil => Nil
    }
  }

它应该可以工作

【讨论】:

    【解决方案3】:

    正如其他人所指出的,编译器试图推断if 表达式的类型(它会尝试找到ifelse 共享的第一个公共超类型)。鉴于缺少 else,它与 Unit 一起使用,因此您收到了错误。

    如果我理解您想要做什么,collecting 似乎是实现这一目标的最简单方法:

    def createSchedules(listTask: List[TaskOrder], physicalResources: List[Physical], humanResources: List[Human], previousTime: Duration): List[TaskSchedule] =
      listTask.collect {
        case TaskOrder(id, time, physicalRes, order) if physicalRes != null =>
          val taskScheduleHumanResources = setHumanResources(physicalRes, humanResources)
          new TaskSchedule(
            order, 
            order.getProduct(), 
            Task(id, time, physicalRes), 
            physicalRes, 
            taskScheduleHumanResources, 
            order.quantity, 
            previousTime, 
            previousTime + time
          )
      }
    

    【讨论】:

    • 这里不支持physicalRes为null时仍然调用setHumanResources的要求。
    猜你喜欢
    • 2021-08-12
    • 1970-01-01
    • 2023-03-26
    • 2022-01-19
    • 2015-12-24
    • 1970-01-01
    • 2022-11-24
    • 2021-01-25
    • 2021-11-15
    相关资源
    最近更新 更多