Scala - 检查列表中是否存在对象

时间:2016-11-08 12:15:22

标签: scala

我试图编写一个算法来检查列表中是否存在对象。

我的案例类如下:

case class Person(id:Int, name:String, friends:List[Person] = Nil)

我使用此代码编写了它:

@tailrec
final def find(id: Int, tree: List[Person]):Option[Person] = tree match {
  case Nil => None
  case (h :: t) => if(h.id == id) Option(h) else find(key, t ::: h.friends)
}

这是一个好方法吗?使用tail递归并在尾部列表中附加另一个列表?如果不是,最好的方法是什么?

1 个答案:

答案 0 :(得分:1)

我最终得到了以下实现,基本上尾递归BFS

@tailrec
def find(id: Int, level: List[Person], visited: Set[Person] = Set.empty): Option[Person] =
  if (level.isEmpty) None
  else {
    // Try to find person on this level
    val found = level.find(_.id == id).filterNot(visited.contains)
    if (found.isDefined) found
    else find(
      id,
      // Next level construction
      level.flatMap(_.friends).distinct,
      // Keep track of visited to handle cycles
      visited ++ level
    )
  }

更新:另外,我建议按名称添加呼叫,以便能够使用更多测试用例:

class Person(val id: Int, val name: String, friends: => List[Person]) {

  def friendList = friends

  override def toString = name
}

object Person {

  def apply(id: Int, name: String, friends: => List[Person] = Nil) = new Person(id, name, friends)
}

在这种情况下,您可以从评论中撰写示例:

val john = Person(1, "john")
val russ = Person(2, "russ")
val bob = Person(3, "bob")
val lois = Person(5, "lois")

lazy val `eve friends` = List(john, anne)
lazy val `peter friends` = List(eve, bob, russ)
lazy val `anne friends` = List(peter, lois)

val eve = Person(7, "eve", `eve friends`)
val peter = Person(8, "peter", `peter friends`)
val anne: Person = Person(6, "anne", `anne friends`)

println(find(8, List(eve, peter, lois))) // result: Some(peter)