scala - 如何按值从列表中删除元素?
问题描述
我目前正在研究一个以 Map[String, List[String]] 和 String 作为参数的函数。该地图包含用户 ID 和他们喜欢的电影的 ID。我需要做的是,返回一个 List[List[String]] ,其中包含喜欢传递给函数的电影的用户喜欢的其他电影。
函数声明如下所示:
def movies(m: Map[String, List[String]], mov: String) : List[List[String]]= {
}
所以让我们想象一下:
val m1 : [Map[Int, List[String]]] = Map(1 ‐> List("b", "a"), 2 ‐> List("y", "x"), 3 ‐> List("c", "a"))
val movieID = "a"
movies(m1, movieId)
这应该返回:
List(List("b"), List("c"))
我试过使用
m1.filter(x => x._2.contains(movieID))
所以只有包含movieID的列表保留在地图中,但我的问题是我需要从它出现的每个列表中删除movieID,然后将结果作为List [List [String]]返回。
解决方案
你可以使用collect
:
val m = Map("1" -> List("b", "a"), "2" -> List("y", "x"), "3" -> List("c", "a"))
def movies(m: Map[String, List[String]], mov: String) = m.collect {
case (_, l) if l.contains(mov) => l.filterNot(_ == mov)
}
movies(m, "a") //List(List(b), List(c))
这种方法的问题在于,它会遍历每个电影列表两次,第一次contains
使用filterNot
. 我们可以优化它的尾递归函数,它会查找元素,如果找到则返回没有它的列表:
import scala.annotation.tailrec
def movies(m: Map[String, List[String]], mov: String) = {
@tailrec
def withoutElement[T](l: List[T], mov: T, acc: List[T] = Nil): Option[List[T]] = {
l match {
case x :: xs if x == mov => Some(acc.reverse ++ xs)
case x :: xs => withoutElement(xs, mov, x :: acc)
case Nil => None
}
}
m.values.flatMap(withoutElement(_, mov))
}
推荐阅读
- javascript - console.log() 不显示实际值
- image - 来自 zarr 文件的 dask 直方图(一个大 zarr 文件)
- azure - Azure Web Bot 服务重置消息传递端点
- scala - 选择后的spark sql where子句
- javascript - 如何在反应中从列表呈现的已删除行上运行加载程序图标?
- postgresql - Postgresql:为什么你不能删除一个不拥有任何资源的具有特权的角色?
- c# - 如何在 Unity(C#,目前针对 iOS)中设置每周重复推送通知?
- php - PHP循环在计数之间的项目周围添加div
- javascript - 将子对象数组排序到带有对象的新数组
- three.js - 在 GLTF 文件中添加交互点