6

我知道 map 函数采用列表(序列)的每个元素并将函数应用于它。递归(并且不考虑终止条件等)

map(s, f) = f(s.head) :: map(s.tail, f)

我正在寻找一个类似的功能

foo(s, f) = f(s) :: map(s.tail, f).

所以一个“映射器”,其中映射函数在子列表而不是单个元素上被调用。在 lisp 术语中,我正在寻找地图列表,而不是地图车。是否存在这样的事情,还是我必须自己推出(或使用递归)?

或者,我将采用一个函数,该函数将一个序列作为输入并返回一个中端子序列序列,即

bar(s, f) = s :: bar(s.tail, f)
4

3 回答 3

5

/* 这种方法用另一种称为tails 的有用方法来定义mapList。和 Daniel 一样,我会将它放在 List 的隐式扩展中,但这纯粹是个人喜好问题 */

implicit def richerList[A](list : List[A]) = new {

/* 这是一个名为 tails 的方法,它返回列表中每个可能的尾部。它是尾递归的,因此它不会在大型列表中爆炸。请注意,它与同名的 Haskell 函数略有不同。Haskell 版本总是在结果中添加一个空列表 */

  def tails : List[List[A]] = {
    def loop(ls : List[A], accum : List[List[A]]) : List[List[A]] = ls match {
      case _ :: tail => loop(tail, ls :: accum)
      case _ => accum
    }

    loop(list, Nil).reverse
  }

/* 这是使用尾部的样子

scala> "abc".toList.tails
res0: List[List[Char]] = List(List(a, b, c), List(b, c), List(c))

*/

/* 现在我们可以根据tails定义mapList */

  def mapList[B](f : List[A] => B) = tails map f
}

/* 这就是使用 mapList 的样子

scala> "abc".toList mapList (_.reverse.mkString)
res1: List[String] = List(cba, cb, c)

*/

于 2009-05-21T14:43:07.143 回答
2

您基本上已经在伪代码中定义了您要查找的内容 - 因此使用隐式转换很容易将这样的方法添加到 Scala 列表中:

object ExtendedList{
  implicit def List2ExtendedList[A](l:List[A])=new ExtendedList(l)
}
class ExtendedList[A](l:List[A]){
  import ExtendedList._
  def mapList[B](f:List[A]=>B):List[B]=l.length match {
    case 0 => List()
    case _ => f(l)::l.tail.mapList(f)
  }
}

object Test extends Application{
  import ExtendedList._
  val test = List(5,4,3,2,1)
  assert(List(15,10,6,3,1)==test.mapList{l=>(0/:l){_+_}})
}

这是你要找的吗?

于 2009-05-21T11:32:02.757 回答
1

另一个答案很接近,但除非绝对必要,否则永远不要使用。List#length特别是,当问题本质上是O(n)时,它使他的解决方案成为O(n^2 ) 。这是一个清理后的版本:

implicit def addListSyntax[A](list: List[A]) = new {
  def mapList[B](f: List[A]=>B) = {
    // use inner function to avoid repeated conversions
    def loop(list: List[A]): List[B] = list match {
      case ls @ (_ :: tail) => f(ls) :: loop(tail)
      case Nil => Nil
    }

    loop(list)
  }
}

而且,要回答您最初的问题:不,没有办法使用标准实用程序方法来做到这一点。我其实有点好奇为什么你会想要这样的东西......

于 2009-05-21T13:33:19.250 回答