在Scala中实施查找和删除

时间:2018-09-04 14:31:10

标签: scala

实现查找和不可变删除Scala集合中第一个出现的函数的方法更容易:

case class A(a: Int, b: Int)

val s = Seq(A(1,5), A(4,6), A(2,3), A(5,1), A(2,7))
val (s1, r) = s.findAndRemove(_.a == 2)

结果:s1 = Seq(A(1,5), A(4,6), A(5,1), A(2,7))r = Some(A(2,3))

4 个答案:

答案 0 :(得分:4)

它找到匹配的第一个元素,并保持顺序。可以使用List而不是Seq进行改进。

case class A(a: Int, b: Int)

val s = Seq(A(1,5), A(4,6), A(2,3), A(5,1), A(2,7))

val (s1, r) = s.findAndRemove(_.a == 2)


println(s1)
println(r)


implicit class SeqOps[T](s:Seq[T]) {

  def findAndRemove(f:T => Boolean):(Seq[T], Option[T]) = {

    s.foldLeft((Seq.empty[T], Option.empty[T])) {
      case ((l, None), elem) => if(f(elem)) (l, Option(elem)) else (l :+ elem, None)
      case ((l, x), elem) => (l :+ elem, x)
    }

  }

}

答案 1 :(得分:4)

是的,聚会晚了一点,但是我想把它扔进去。

  • 谓词的最小调用。
  • 适用于最受欢迎的集合类型:SeqListArrayVector。甚至SetMap(但对于那些集合,它们没有保留顺序,也无法确定谓词将首先找到哪个元素)。不适用于IteratorString

-

import scala.collection.generic.CanBuildFrom
import scala.language.higherKinds

implicit class CollectionOps[U, C[_]](xs :C[U]) {
  def findAndRemove(p :U=>Boolean
                   )(implicit bf :CanBuildFrom[C[U], U, C[U]]
                             ,ev :C[U] => collection.TraversableLike[U, C[U]]
                   ) :(C[U], Option[U]) = {
    val (before, after) = xs.span(!p(_))
    before ++ after.drop(1) -> after.headOption
  }
}

用法:

case class A(a: Int, b: Int)
val (as, a) = Seq(A(1,5), A(4,6), A(2,3), A(5,1), A(2,7)).findAndRemove(_.a==2)
//as: Seq[A] = List(A(1,5), A(4,6), A(5,1), A(2,7))
//a: Option[A] = Some(A(2,3))

val (cs, c) = Array('g','t','e','y','b','e').findAndRemove(_<'f')
//cs: Array[Char] = Array(g, t, y, b, e)
//c: Option[Char] = Some(e)

val (ns, n) = Stream.from(9).findAndRemove(_ > 10)
//ns: Stream[Int] = Stream(9, ?)
//n: Option[Int] = Some(11)
ns.take(5).toList  //List[Int] = List(9, 10, 12, 13, 14)

答案 2 :(得分:2)

尝试这样的事情

def findAndRemove(as: Seq[A])(fn: A => Boolean): (Seq[A], Option[A]) = {
    val index = as.indexWhere(fn)
    if(index == -1) as -> None
    else as.patch(index, Nil, 1) -> as.lift(index)
}

val (s1, r) = findAndRemove(s)(_.a == 2)

答案 3 :(得分:0)

我的版本:

def findAndRemove(s:Seq[A])(p:A => Boolean):(Seq[A], Option[A])={
  val i = s.indexWhere(p)
  if(i > 0){
    val (l1, l2) = s.splitAt(i)
    (l1++l2.tail, Some(l2.head))
  }else{
    (s, None)
  }
}