6

map 関数はリスト (シーケンス) の各要素を取り、それに関数を適用することを知っています。再帰的に(終了条件などに関係なく)

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

次のような機能を探しています

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

したがって、マッピング関数が個々の要素ではなくサブリストで呼び出される「マッパー」。Lisp 用語で言えば、mapcar ではなく、maplist を探しています。このようなものは存在しますか、それとも自分でロールする (または再帰を使用する) 必要がありますか?

別の方法として、入力としてシーケンスを受け取り、途中から最後のサブシーケンスのシーケンスを返す関数を使用します。つまり、

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

*/

/* これで、テールに基づいて 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 に答える
1

もう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 に答える