6

たとえば、数字のリストがあり、各数字に 2 と 3 を掛けたものを含むリストを作成したいとします。次のようなことを行う方法はありますか?数のリストのリスト?

mult_nums = [ [(n*2),(n*3)] | n <- [1..5]] 
-- this returns [[2,3],[4,6],[6,9],[8,12],[10,15]]
-- but we want [2,3,4,6,6,9,8,12,10,15]
4

3 に答える 3

17

リスト内包表記を拡張すると、これが読みやすくなることがわかりました。

[ m | n <- [1..5], m <- [2*n,3*n] ]

これが何をするのか、そしてそれが他のソリューションとどのように関連しているかを正確に調べることが役立つかもしれません。それを関数として定義しましょう:

mult lst = [ m | n <- lst, m <- [2*n,3*n] ]

ファッションの後、これは脱糖します

mult' lst = 
    concatMap (\n -> concatMap (\m -> [m]) [2*n,3*n]) lst

concatMap (\m -> [m])m、すぐにフラット化するためにリストにまとめられています。これは、と同等map idです。

これを@FunctorSaladの答えと比較してください:

mult1 lst = concatMap (\n -> [n*2,n*3]) lst

最適化しましたconcatMap (\m -> [m])

今@viliの答え:

mult2 lst = concat [ [(n*2),(n*3)] | n <- lst]

これは次のように脱糖します:

mult2' lst = concat (concatMap (\n -> [[2*n,3*n]]) lst)

上記の最初のソリューションと同様に、削除する必要のあるリストのリストを不必要に作成してconcatいます。

リスト内包表記を使用する解決策はないと思いますが、脱糖しmult1ます。私の直感では、Haskellコンパイラーは一般的に十分に賢いので、これは問題になりません(あるいは、concat遅延評価のために不要なものは安価です(熱心な言語では致命的です))。

于 2009-02-20T03:40:59.027 に答える
13

concat を使用できます。

concat [ [(n*2),(n*3)] | n <- [1..5]] 
output: [2,3,4,6,6,9,8,12,10,15]
于 2009-02-20T00:25:29.167 に答える
5

同様のケースでは、concatMap も便利ですが、ここではあまり変わりません。

concatMap (\n -> [n*2,n*3]) [1..5]
于 2009-02-20T00:30:42.557 に答える