【发布时间】:2019-04-25 06:14:36
【问题描述】:
给定一个 Seq[Person],其中包含 1-n 个Persons(以及最少 1 个人蜂鸣“汤姆”),找到带有名称的 Person 的最简单方法是什么“汤姆”以及在汤姆之前的人和在汤姆之后的人?
更详细的解释:
case class Person(name:String)
人员列表可以任意长,但至少有一个条目,必须是“Tom”。所以这些列表可能是一个有效的案例:
val caseOne = Seq(Person("Tom"), Person("Mike"), Person("Dude"),Person("Frank"))
val caseTwo = Seq(Person("Mike"), Person("Tom"), Person("Dude"),Person("Frank"))
val caseThree = Seq(Person("Tom"))
val caseFour = Seq(Person("Mike"), Person("Tom"))
你明白了。由于我已经有了“汤姆”,因此任务是获取他的左邻居(如果存在)和右邻居(如果存在)。
在 scala 中实现这一目标的最有效方法是什么?
我目前的做法:
var result:Tuple2[Option[Person], Option[Person]] = (None,None)
for (i <- persons.indices)
{
persons(i).name match
{
case "Tom" if i > 0 && i < persons.size-1 => result = (Some(persons(i-1)), Some(persons(i+1))) // (...), left, `Tom`, right, (...)
case "Tom" if i > 0 => result = (Some(persons(i-1)), None) // (...), left, `Tom`
case "Tom" if i < persons.size-1 => result = (Some(persons(i-1)), None) // `Tom`, right, (...)
case "Tom" => result = (None, None) // `Tom`
}
}
只是不觉得我在做 scala 方式。
Mukesh prajapati 的解决方案:
val arrayPersons = persons.toArray
val index = arrayPersons.indexOf(Person("Tom"))
if (index >= 0)
result = (arrayPersons.lift(index-1), arrayPersons.lift(index+1))
很短,似乎涵盖了所有情况。
anuj saxena 的解决方案
result = persons.sliding(3).foldLeft((Option.empty[Person], Option.empty[Person]))
{
case ((Some(prev), Some(next)), _) => (Some(prev), Some(next))
case (_, prev :: Person(`name`) :: next :: _) => (Some(prev), Some(next))
case (_, _ :: prev :: Person(`name`) :: _) => (Some(prev), None)
case (_, Person(`name`) :: next :: _) => (None, Some(next))
case (neighbours, _) => neighbours
}
【问题讨论】:
-
Person是案例类吗? -
是的。更新了问题以澄清。
-
Mukesh 的解决方案很好,但如果“Tom”实际上不在集合中,它会给出错误/误导性的结果。
-
在这种情况下,应该检查
index == -1以避免问题,所以它不是问题。
标签: scala collections filtering sliding-window