FP:如何过滤列表[A],这样它将包含除选项[A]之外的所有元素



这是一个更有教育意义的答案,因为我有工作的解决方案,但我觉得应该有一些我错过的函数式编程模式或概念,我想学习它。

假设我有一个List[Player],其中Player是案例类。我也有Option[Player],我想编写方法,该方法将返回列表中的所有元素,除了(可能Option!这是代码

case class Player(id:Long)
val players = List(Player(1), Player(2), Player(3))
var boss = None
def findAllExceptBoss = {
players.filter(boss != Some(_))
}
findAllExceptBoss.size should be (3)
var boss = Some(Player(1))
findAllExceptBoss.size should be (2)

所以,我的问题是 - 我如何以更实用的风格实现players.filter(boss != Some(_))? 谢谢!

如果没有命名老板,则无需搜索列表,因此请排除搜索因素。

case class Player(id:Long)
val players = List(Player(1), Player(2), Player(3))
var boss: Option[Player] = None
def findAllExceptBoss = {
boss match {
case Some(b) => players.filter(b != _)
case None => players
}
}
findAllExceptBoss.size should be (3)
boss = Some(Player(1))
findAllExceptBoss.size should be (2)

我经常发现fold()是一个方便的Option展开器。

boss.fold(players)(b => players.filterNot(_.id == b.id))

这样,如果没有必要,则无需遍历players

首先,你不应该在函数中使用var。我会做这样的事情:

def findAllExceptBoss(boss: Option[Player])(players: List[Player]): List[Player] = {
boss.map(b => players.filter(p => p != b).getOrElse(players)
}
findAllExceptBoss(None)(players).size should be (3)

这也将允许您执行以下操作:

def filterForSpecificBoss = findAllException(boss)
val filtered = filterForSpecificBoss(players)

尊重您的方法定义,我会选择:

def findAllExceptBoss= 
for { 
p <- players
b <- boss
if p != b
} yield p

正确的方法是players.filterNot(boss.toSet)另外,不要使用vars,它们不好。

最新更新