3

要素のシーケンスと述語が与えられた場合、各サブシーケンスで、すべての要素が満たされるか、シーケンスが長さを持つpように、シーケンスのシーケンスを生成したいと思います。さらに、結果を呼び出すと、元のシーケンスが返されます (したがって、要素の並べ替えはありません)。p1.flatten

たとえば、次のようになります。

val l = List(2, 4, -6, 3, 1, 8, 7, 10, 0)
val p = (i : Int) => i % 2 == 0

magic(l,p)私は生産したいと思います:

List(List(2, 4, -6), List(3), List(1), List(8), List(7), List(10, 0))

については知って.spanいますが、そのメソッドは、満たさない値に最初に遭遇したときに停止しp、ペアを返すだけです。

以下は実装候補です。それは私が望むことをしますが、まあ、私たちは泣きたくなる. 誰かがもう少し慣用的なものを考え出してほしいです。

def magic[T](elems : Seq[T], p : T=>Boolean) : Seq[Seq[T]] = {
  val loop = elems.foldLeft[(Boolean,Seq[Seq[T]])]((false,Seq.empty)) { (pr,e) =>
    val (lastOK,s) = pr
    if(lastOK && p(e)) {
      (true, s.init :+ (s.last :+ e))
    } else {
      (p(e), s :+ Seq(e))
    }
  }
  loop._2
}

( の実際の型を保持することは特に気にしないことに注意してくださいSeq。)

4

3 に答える 3

3

私は使用しませんfoldLeftspanヘッドが述語と一致しない場合は、特別なルールを使用した単純な再帰です。

def magic[T](elems: Seq[T], p: T => Boolean): Seq[Seq[T]] = 
  elems match {
    case Seq() => Seq()
    case Seq(head, tail @ _*) if !p(head) => Seq(head) +: magic(tail, p)
    case xs => 
      val (prefix, rest) = xs span p
      prefix +: magic(rest, p)
  }

末尾再帰を行うこともできますが、先頭に追加する場合は出力を逆にすることを覚えておく必要があります (賢明な方法です)。

def magic[T](elems: Seq[T], p: T => Boolean): Seq[Seq[T]] = {
  def iter(elems: Seq[T], out: Seq[Seq[T]]) : Seq[Seq[T]] = 
    elems match {
      case Seq() => out.reverse
      case Seq(head, tail @ _*) if !p(head) => iter(tail, Seq(head) +: out)
      case xs => 
        val (prefix, rest) = xs span p
        iter(rest, prefix +: out)
    }
  iter(elems, Seq())
}
于 2013-01-10T19:32:06.380 に答える
3

このタスクでは、再帰に一致する小さなパターンを使用takeWhileして組み合わせることができます。drop

def magic[T](elems : Seq[T], p : T=>Boolean) : Seq[Seq[T]] = {
  def magic(elems: Seq[T], result: Seq[Seq[T]]): Seq[Seq[T]] = elems.takeWhile(p) match {
    // if elems is Nil, we have a result
    case Nil if elems.isEmpty => result

    // if it's not, but we don't get any values from takeWhile, we take a single elem
    case Nil => magic(elems.tail, result :+ Seq(elems.head))

    // takeWhile gave us something, so we add it to the result
    // and drop as many elements from elems, as takeWhile gave us
    case xs => magic(elems.drop(xs.size), result :+ xs)
  }

  magic(elems, Seq())
}
于 2013-01-10T16:36:29.983 に答える
0

折り畳みを使用した別のソリューション:

def magicFilter[T](seq: Seq[T], p: T => Boolean): Seq[Seq[T]] = {
  val (filtered, current) = (seq foldLeft (Seq[Seq[T]](), Seq[T]())) {
    case ((filtered, current), element) if p(element)       => (filtered, current :+ element)
    case ((filtered, current), element) if !current.isEmpty => (filtered :+ current :+ Seq(element), Seq())
    case ((filtered, current), element)                     => (filtered :+ Seq(element), Seq())
  }
  if (!current.isEmpty) filtered :+ current else filtered
}
于 2013-01-10T17:14:28.657 に答える