2016-09-06 17 views
0

私はスカラを教えていて、自分のFPスキルを肥えています。スカラのネストされたリストを再帰的に処理する

プログラミング言語の基礎(available here)の参考文献の1つに、簡単な再帰関数の便利なリストがあります。ページ27/50のページでは、swapper()関数を実装するように求められています。 Scalaで

(swapper s1 s2 slist) returns a list the same as slist, but 
with all occurrences of s1 replaced by s2 and all occurrences of s2 replaced by s1. 


> (swapper ’a ’d ’(a b c d)) 
(d b c a) 
> (swapper ’a ’d ’(a d() c d)) 
(d a() c a) 
> (swapper ’x ’y ’((x) y (z (x)))) 
((y) x (z (y))) 

、これは次のようになります。

swapper("a", "d", List("a","b","c","d")) 
swapper("a", "d", List("a","d",List(),"c","d")) 
swapper("x", "y", List(List("x"), "y", List("z", List("x")))) 

マイScalaのバージョンでは、すべてのバージョンが最終的なXを保存処理します。

def swapper(a: Any, b: Any, lst: List[Any]): List[Any] ={ 
    def r(subList :List[Any], acc : List[Any]): List[Any] ={ 
    def swap (x :Any, xs: List[Any]) = 
     if(x == a){ 
     r(xs, acc :+ b) 
     } else if (x == b) { 
     r(xs, acc :+ a) 
     } else { 
     r(xs, acc :+ x) 
     } 
    subList match { 
    case Nil => 
     acc 
    case List(x) :: xs => 
     r(xs, r(List(x), List()) +: acc) 
    case x :: xs => 
     swap(x,xs) 
    //case List(x) :: xs => 
    } 
    } 
    r(lst, List()) 
} 

本能的に、私は「XS ::ケース一覧(x)は、」私はセクションにはスワップを持っていないので、これがあると思いますが、私はまだそれを修正するために苦労しています。

さらに難しく、この場合でもテールコールの最適化は中断されます。私はこれをどうやって行うことができますか?一般的な解決法についてもっと知るためにどこに行くことができますか?

かさえsimplier(@marcospereiraのおかげで)::

def swapper(a:Any, b:Any, list:List[Any]):List[Any] = 
    list.map { 
    case item if item==a => b 
    case item if item==b => a 
    case item:List[Any] => swapper(a, b, item) 
    case item => item 
    } 

答えて

2

あなたはこのパターンマッチのアプローチとfoldRightを使用することができます

def swapper[T](a: T, b: T, list: List[T]): List[T] = list.map { item => 
    if (item == a) b 
    else if (item == b) a 
    else item 
} 
+0

OK!あなたの洞察をお寄せいただきありがとうございます。 @tailrecアノテーションを追加すると、再帰呼び出しは文句を言いませんが、末尾の位置ではありません。 – peoplemerge

1

だけmapを使用しているこの問題を解決するための簡単な方法:

+0

OPの3番目のテストケースを処理していないようです。 – jwvh

1

これは動作するようです。それは要素であるかもしれないまたはタイプは、誰かがこのデータ表現を再考する必要があることを確認してくださいため息あるList[Any]、あるので、それは、別のList可能性があるため

def swapper[T](a: T, b: T, lst: List[_]): List[_] = { 
    val m = Map[T, T](a -> b, b -> a).withDefault(identity) 
    def swap(arg: List[_]): List[_] = arg.map{ 
    case l: List[_] => swap(l) 
    case x: T => m(x) 
    } 
    swap(lst) 
} 

List要素が矛盾しています。

関連する問題