在Scala中使用for comprehension时修改列表

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了在Scala中使用for comprehension时修改列表相关的知识,希望对你有一定的参考价值。

我有一个包含客户之间所有可能交易的清单,并且需要比较每个买卖组合。通过比较,需要修改另一个列表。

我有以下代码:

def res(input_orders: List[Order], input_clients: List[Client]): List[Client] = {
  for {
    order1 <- input_orders
    order2 <- input_orders if check_order(order1, order2)
    firstClient = input_clients.find(_.name == order1.client)
    secondClient = input_clients.find(_.name == order2.client)
    tmp <- if (order1.operation == 's') {    
      input_clients.map { case `firstClient` => sell(firstClient.get, order1); case x => x }
      input_clients.map { case `secondClient` => buy(secondClient.get, order2); case x => x }
    } else {
      input_clients.map { case `firstClient` => buy(firstClient.get, order1); case x => x }
      input_clients.map { case `secondClient` => sell(secondClient.get, order2); case x => x }
    }
  } yield tmp
}

但它按原样返回客户端列​​表,不会对其进行修改。

我想问题出在这个“修改”块中:

  input_clients.map { case `firstClient` => sell(firstClient.get, order1); case x => x }
  input_clients.map { case `secondClient` => buy(secondClient.get, order2); case x => x }
} else {
  input_clients.map { case `firstClient` => buy(firstClient.get, order1); case x => x }
  input_clients.map { case `secondClient` => sell(secondClient.get, order2); case x => x }

这有什么问题?

答案

回想一下,map函数是不可变的,这意味着它不会对数据结构进行任何修改,而是返回一个内容已更新的新对象。

在你提到的块中,mapare的第一次调用没用,因为从不使用返回值。实现您最初想要完成的任务的正确方法是:

val order = order1.operation == 's'
input_clients.map {
  case `firstClient` => if (order) sell(firstClient.get, order1) else buy(firstClient.get, order1)
  case `secondClient` => if (order) buy(secondClient.get, order2) else sell(secondClient.get, order2)
  case x => x
}

此外,避免使用getOption[T]访问器(想象如果选项是None会发生什么)。更喜欢更安全的操作,如模式匹配或flatMap / for-comprehension。

以上是关于在Scala中使用for comprehension时修改列表的主要内容,如果未能解决你的问题,请参考以下文章

Scala-流程控制

Scala中的yield关键字| for / yield示例

2021年大数据常用语言Scala:基础语法学习 循环

16.scala的For 表达式

在 Scala 中使用索引进行高效迭代

为啥必须在scala的for循环中为模式匹配定义过滤器?