Scala:在一次调用中将相同的函数应用于 2 个列表

标签 scala scalaz

假设我有

val list: List[(Int, String)] = List((1,"test"),(2,"test2"),(3,"sample"))

我需要根据(Int,String)值将此列表分为两部分。到目前为止,一切都很好。 例如它可以是

def isValid(elem: (Int, String)) = elem._1 < 3 && elem._2.startsWith("test")
val (good, bad) = list.partition(isValid)

所以,现在我有 2 个带有签名 List[(Int, String)] 的列表,但我只需要 Int 部分(一些 id)。当然我可以写一些函数

def ids(list:List(Int, String)) = list.map(_._1)

并在两个列表上调用它

val (ok, wrong) = (ids(good), ids(bad))

它有效,但看起来有点样板。我更喜欢类似的东西

val (good, bad) = list.partition(isValid).map(ids)

但这显然不可能。那么有没有“更好”的方式来做我需要的事情呢? 我知道这还不错,但觉得这种情况存在一些功能模式或通用解决方案,我想知道:) 谢谢!

附注感谢大家!最后转化为

private def handleGames(games:List[String], lastId:Int) = {
  val (ok, wrong) = games.foldLeft(
  (List.empty[Int], List.empty[Int])){
    (a, b) => b match {
      case gameRegex(d,w,e) => {
        if(filterGame((d, w, e), lastId)) (d.toInt :: a._1, a._2)
        else (a._1, d.toInt :: a._2 )
      }
      case _ => log.debug(s"not handled game template is: $b"); a
    }
  }
  log.debug(s"not handled game ids are: ${wrong.mkString(",")}")
  ok
}

最佳答案

您正在列表上查找foldLeft:

myList.foldLeft((List.empty[Int], List.empty[Int])){
  case ((good, bad), (id, value)) if predicate(id, value) => (id :: good, bad)
  case ((good, bad), (id, _)) => (good, id :: bad)
}

这样,您就可以在每个阶段进行转换和累积。返回的类型将为 (List[Int], List[Int]) 假设 predicate 是在“好”和“坏”状态之间进行选择的函数。 Nil 的强制转换是由于 Scala 在 Foldl 上选择最严格的类型的激进本质。

关于Scala:在一次调用中将相同的函数应用于 2 个列表,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/47204791/

相关文章:

scala - Intellij IDEA : Run Scala REPL Console on a remote machine.

scala - 如何创建循环流?

scala - 使用 Scalaz(或 Shapeless)为每个子类创建 Monoid

scala - 使用 Scalaz 流,如何将 A => Task[B] 转换为 Process1[A,B]

Scala:将特征与私有(private)字段混合

scala - 定义多个特征的最佳实践,这些特征将行为添加到实现特定特征的类中

scala - 如何在Scala中实现 `List` monad变压器?

scala - 使用 Scalaz 7 zipWithIndex/group enumeratees 避免内存泄漏

scala - 将文件从主机复制到容器时,Docker COPY错误

mongodb - java.lang.NoSuchFieldException : handle Embedded MongoDB with play framework 异常