2017-12-18 7 views
2

私は地図の中で '頭の'機能を使いたいです。 問題は、 'head'関数は空でないリストだけを受け入れることです。私は私が一度リストのリストを反復または「IF条件」を置くことができるかどうか思ったんだけど二回空のリストの発行のためのヘッド機能

let listOne = filter(\x -> if length x > 0) ll 
map(\x -> head x) listOne 

をリストのリストを反復処理する必要が

let ll =[["dog", "cat"], ["pig", "cow"], []] 

: 私はリストのリストを持っています「フィルタ」

無しマップ内部の提案が理解されるであろう。

+1

空リストの場合はどうしますか?フィルタリング/無視するだけですか?なぜフィルターはあなたが望むことをしないのですか? – puhlen

+0

フィルタは空のリストだけを削除しますが、head要素を使用してhead要素で何かします。 –

+0

しかし、空のリストには頭がありません。あなたはmap + filterが何をしていないのですか?あなたがリストを2度反復しているだけであれば、それはしません。これらの操作は遅延して評価されます。 – puhlen

答えて

8

はい、実際にあなたがリストの内包文としてそれを書き、その代わりマッチングパターン使用することができます。私たちはだからここ

heads :: [[a]] -> [a] 
heads ll = [ h | (h:_) <- ll ] 

result = [ h | (h:_) <- ll ] 

や機能などを空でないすべてのリストと一致するパターン(h:_)を使用し、直接そのリストのhというヘッドを取得し、それをリストに追加します。リスト内包(左矢印<-の左側にパターンを使用すると、パターンに一致しない要素はスキップされます)。

あなたは無限リストで作業している場合lengthが無限ループにはまりますので、これは、またlengthを使用するよりも安全なよりです。さらに、非合計要素数がhead以上のパターンを使用すると、構文がであることが保証されます(空でない要素がフィルタリングされると、headはエラーにならないことはもちろんですがhead関数についての情報があるので、これだけを知ることができます)。

ifを使用しているため、thenelseの部分を使用しないと、構文エラーが発生することに注意してください。また

、我々は、@DanielWagnerが言うように、使用して、インスタンスのために、異なったheads関数を書くことができます。

heads :: [[a]] -> [a] 
heads ll = concatMap (take 1) ll 

かによってをリストモナドのバインド使用:

heads :: [[a]] -> [a] 
heads = (take 1 =<<) 

かを2dリストを転置することができます。その場合、最初の行にはリストのすべての頭が含まれます。ただし、そのような行があることは保証されていないため、末尾に空のリストを追加することができます。

heads :: [[a]] -> [a] 
heads = head . (++ [[]]) . transpose 
+2

同じアイデアの別の楽しいスペル: 'heads = concatMap(take 1)'。まったく異なるアイデア: 'heads = head。 (++ [[]])。転置する。 –

+0

@DanielWagner:私はこれらが本当に好きです。特に最初のものが特に好きです。 –

関連する問題