3

私はHaskellを初めて使用し、基本を習得しようとしています。

次のリスト y があるとします。

3:3:2:1:9:7:3:[]

リスト y で最初に出現した 3 を削除する方法を見つけようとしています。これは単純なリスト内包表記を使用して可能ですか?

私が試したこと(この方法はリストからすべてのインスタンスを削除します):

deleteFirst _ [] = [] 
deleteFirst a (b:bc) | a == b    = deleteFirst a bc 
                     | otherwise = b : deleteFirst a bc
4

4 に答える 4

6

いいえ、リスト内包表記を使用することはできません。リスト内包表記では、その要素のみに基づいて保持する要素を決定します。あなたの例では、遭遇した最初の3つを他の3つとは異なる方法で扱いたいので(最初のものだけを削除したいため)、決定は要素だけに依存しません。したがって、リスト内包表記は機能しません。

あなたが言ったように、すべてのインスタンスを削除することを除いて、再帰関数を使用する試みはすでにかなり近いです。すべてのインスタンスを削除するのはなぜですか? deleteFirst最初のものを削除した後、リストの残りの部分を再度呼び出すと、次のインスタンスが削除されるためです。deleteFirstこれを修正するには、最初のインスタンスを削除した後に再度呼び出さないでください。bcその場合は代わりに使用deleteFirst a bcしてください。

于 2013-02-04T14:27:16.213 に答える
4

すでに述べたように、リスト内包表記はこのタスクの適切な解決策ではありません (1 つのステップで実行を終了するのは困難です)。

一致した値と等しい場合、一致した要素なしで残りのリストを返すことによって計算を終了する必要があっただけで、ほとんど正しいソリューションを記述しました。

deleteFirst _ [] = [] 
deleteFirst a (b:bc) | a == b    = bc 
                     | otherwise = b : deleteFirst a bc

> print $ deleteFirst 3 (3:3:2:1:9:7:3:[])
> [3,2,1,9,7,3]
于 2013-02-04T16:06:03.970 に答える
2

リストの理解でこれを行うことが可能だとは思いません(少なくとも慣用的な方法ではありません)。

あなたのdeleteFirst作品はほとんど。修正するために変更する必要があるのは、最初の一致の後に削除を停止することです。つまりdeleteFirst a bc、最初の句を で置き換えbcます。

于 2013-02-04T14:26:37.673 に答える
0

リスト内包表記に関する sepp2k の発言は、理解することが重要です。、などのリスト操作はmap、すべてのリスト項目を一様に扱います。それらについて理解する重要なことは、各ステップでどのような情報が利用できるか、および各ステップの結果が他のステップの結果とどのように組み合わされるかです。filterfoldr

しかし、私が強調したい側面は、これらの問題をライブラリ関数の観点から解決しようとするべきだと思うということです。私のこの古い回答から解決策をあなたの問題に適応させる:

deleteFirst x xs = beforeX ++ afterX
    -- Split the list into two pieces:
    --   * prefix = all items before first x
    --   * suffix = all items after first x
    where (beforeX, xAndLater) = break (/=x) xs
          afterX = case xAndLater of
                     [] -> []
                     (_:xs) -> xs

トリックはbreak、「最初のヒットまで」の動作が既に組み込まれていることです。breakさらなる演習として、独自のバージョンの;を書いてみることができます。これらの小さくて汎用的で再利用可能な関数の書き方を学ぶことは、常に有益です。

于 2013-02-04T21:31:30.383 に答える