在塞克[人]中查找人和直系邻居

时间:2018-11-22 14:24:23

标签: scala collections filtering sliding-window

给出一个function[x, y, z, s] = getXYZ(pathData, j, i, s) fullDataPath = sprintf(...); fileAllData = importdata(fullDataPath); m = fileAllData{i,1}.(attivita{1,j}){s,1}; x = m(1,:)'; y = m(2,:)'; z = m(3,:)'; ..... s = s+1; end Main function: ..... for j = 1:K for i = 1:nSubjects s = 1; while s<=trials(j) [x, y, z, s] = getXYZ(pathData, j, i, s); end end end ... ,其中包含1- n Seq[Person]个(以及最少1个人为“ Tom”),找到{ {1}}的名称为“ Tom”,以及Tome之前的人 和Tom后面的人

更详细的解释:

Person

人员列表可以任意长,但至少要包含个条目,该条目必须为“ Tom”。因此,这些列表可能是有效的情况:

Person

您明白了。由于我已经有了“汤姆”,所以任务是让他的左邻居(如果存在)和右邻居(如果存在)。

在Scala中实现此目的的最有效方法是什么?


我当前的做法:

case class Person(name:String)

只是觉得我不是在以 scala方式这样做。


Mukesh prajapati的解决方案:

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"))

相当简短,似乎涵盖了所有情况。


anuj saxena的解决方案

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`
  }
}

5 个答案:

答案 0 :(得分:2)

首先找出存在“ Tom”的索引,然后使用“ lift”。 “ lift”将部分函数转换为简单函数,并返回Option结果:

index = persons.indexOf("Tom")
doSomethingWith(persons.lift(index-1), persons.lift(index+1))

答案 1 :(得分:1)

经验法则:我们绝不应该使用索引来访问列表/ seq的内容,因为它容易出错(例如IndexNotFoundException)。

如果我们要使用索引,则最好使用Array,因为它为我们提供了随机访问权限。

对于当前解决方案,这是我的代码,用于在SeqList中查找某些数据的上一个和下一个元素:

  def findNeighbours(name: String, persons: Seq[Person]): Option[(Person, Person)] = {
    persons.sliding(3).flatMap{
      case prev :: person :: next :: Nil if person.name == name => Some(prev, next)
      case _ => None
    }.toList.headOption
  }

这里的返回类型在Option中,因为有可能我们在这里找不到它(如果列表中只有一个人或列表中没有所需的人)。

此代码将在参数中提供的person首次出现时选择该对。

如果所提供的人可能有几次出现,请删除函数findNeighbours的最后一行中的headOption。然后它将返回一个元组列表。

更新

如果Person是一个案例类,那么我们可以像这样使用深度匹配:

  def findNeighbours(name: String, persons: Seq[Person]): Option[(Person, Person)] = {
    persons.sliding(3).flatMap{
      case prev :: Person(`name`) :: next :: Nil => Some(prev, next)
      case _ => None
    }.toList.headOption
  }

对于您的解决方案,需要向其添加更多案例(将其更改为在单个答案的情况下使用foldleft):

  def findNeighboursV2(name: String, persons: Seq[Person]): (Option[Person], Option[Person]) = {
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
}

}

答案 2 :(得分:0)

您可以使用滑动功能:

persons: Seq[Person] = initializePersons()
persons.sliding(size = 3).find { itr =>
  if (itr(1).name = "Tom") {
    val before = itr(0)
    val middle = itr(1)
    val after = itr(2)
  }
}

答案 3 :(得分:0)

如果您知道Seq中将只有一个“ Tom”实例,请使用indexOf而不是手工循环:

tomIndex = persons.indexOf("Tom")
doSomethingWith(persons(tomIndex-1), persons(tomIndex+1))

答案 4 :(得分:0)

// Start writing your ScalaFiddle code here
case class Person(name: String)

val persons1 = Seq(Person("Martin"),Person("John"),Person("Tom"),Person("Jack"),Person("Mary"))
val persons2 = Seq(Person("Martin"),Person("John"),Person("Tom"))
val persons3 = Seq(Person("Tom"),Person("Jack"),Person("Mary"))
val persons4 = Seq(Person("Tom"))

def f(persons:Seq[Person]) = 
  persons
    .sliding(3)
    .filter(_.contains(Person("Tom")))
    .maxBy {
      case _ :: Person("Tom") :: _ => 1
      case _                       => 0
    }
    .toList
    .take(persons.indexOf(Person("Tom")) + 2) // In the case where "Tom" is first, drop the last person
    .drop(persons.indexOf(Person("Tom")) - 1) // In the case where "Tom" is last, drop the first person

println(f(persons1)) // List(Person(John), Person(Tom), Person(Jack))
println(f(persons2)) // List(Person(John), Person(Tom))
println(f(persons3)) // List(Person(Tom), Person(Jack))
println(f(persons4)) // List(Person(Tom))

Scalafiddle