Scala-序列的递增前缀

Scala-序列的递增前缀,scala,Scala,我想知道获取给定序列的递增前缀最优雅的方法是什么。我的想法如下,但它不是纯粹的功能或任何优雅: val sequence = Seq(1,2,3,1,2,3,4,5,6) var currentElement = sequence.head - 1 val increasingPrefix = sequence.takeWhile(e => if (e > currentElement) { currentElement = e

我想知道获取给定序列的递增前缀最优雅的方法是什么。我的想法如下,但它不是纯粹的功能或任何优雅:

val sequence = Seq(1,2,3,1,2,3,4,5,6)
var currentElement = sequence.head - 1
val increasingPrefix = sequence.takeWhile(e =>
            if (e > currentElement) {
                currentElement = e
                true
            } else
                false)
上述结果是:

List(1,2,3)
如果你所说的优雅是指简洁和不言自明,那么可能是如下所示:

sequence.inits.dropWhile(xs => xs != xs.sorted).next
inits
为我们提供了一个迭代器,它首先返回最长前缀。我们删除所有未排序的,然后选择下一个

如果不想进行所有排序,可以编写如下内容:

sequence.scanLeft(Some(Int.MinValue): Option[Int]) {
  case (Some(last), i) if i > last => Some(i)
  case _ => None
}.tail.flatten

但是,如果此操作的性能非常重要(可能不是),您需要使用更重要的功能,因为此解决方案仍然会遍历整个集合(两次)。

您可以使用您的解决方案@Samlik,并有效地压缩
currentElement
变量,但当你完成后,再把它画出来

sequence.take(1) ++ sequence.zip(sequence.drop(1)).
    takeWhile({case (a, b) => a < b}).map({case (a, b) => b})
序列
现在是一个无限的
,但我们可以看到前10项:

scala> sequence.take(10).toList
res: List[Int] = List(1, 2, 3, 1, 2, 3, 4, 5, 6, 7)
现在,使用上面的代码片段:

val prefix = sequence.take(1) ++ sequence.zip(sequence.drop(1)).
    takeWhile({case (a, b) => a < b}).map({case (a, b) => b})

注意:这不适用于
序列
为空或前缀也是无限的情况。

我将优雅解释为最类似于我们人类思考问题的方式的解决方案,尽管极其高效的算法也可能是优雅的一种形式

scala> prefix.toList
res: List[Int] = List(1, 2, 3)
val sequence = List(1,2,3,2,3,45,5)
val increasingPrefix = takeWhile(sequence, _ < _)

还有另一种剥猫皮的方法:

 val sequence = Seq(1,2,3,1,2,3,4,5,6)
 sequence.head :: sequence
                  .sliding(2)
                  .takeWhile{case List(a,b) => a <= b}
                  .map(_(1)).toList
// List[Int] = List(1, 2, 3)
val序列=序列(1,2,3,1,2,3,4,5,6)
sequence.head::sequence
.滑动(2)

.takeWhile{case List(a,b)=>a我也喜欢这种方法。它可以广泛使用
/**
 * Takes elements from a sequence by applying a predicate over two elements at a time.
 * @param xs The list to take elements from
 * @param f The predicate that operates over two elements at a time
 * @return This function is guaranteed to return a sequence with at least one element as
 *         the first element is assumed to satisfy the predicate as there is no previous
 *         element to provide the predicate with.
 */
def takeWhile[A](xs: Traversable[A], f: (Int, Int) => Boolean): Traversable[A] = {
  // function that operates over tuples and returns true when the predicate does not hold
  val not = f.tupled.andThen(!_)
  // Maybe one day our languages will be better than this... (dependant types anyone?)
  val twos = sequence.sliding(2).map{case List(one, two) => (one, two)}
  val indexOfBreak = twos.indexWhere(not)
  // Twos has one less element than xs, we need to compensate for that
  // An intuition is the fact that this function should always return the first element of
  // a non-empty list
  xs.take(i + 1)
}
 val sequence = Seq(1,2,3,1,2,3,4,5,6)
 sequence.head :: sequence
                  .sliding(2)
                  .takeWhile{case List(a,b) => a <= b}
                  .map(_(1)).toList
// List[Int] = List(1, 2, 3)