2017-01-10 14 views
0

から1つの要素を削除するにはすべての可能な方法は、これは私がこれまで書いてきたものですが、私は失われたビットを得ている:Haskellのリスト

removeone :: [a] -> [[a]] 
removeone [] = [] 
removeone (a:as) = [as] -- I'm lost here 

は、これは私が探していた出力の一種でありますfor:

removeone [1,2,3] = [[2,3],[1,3],[1,2]] 
removeone [1,2] = [[1],[2]] 

この問題を解決するにはどうすればよいでしょうか? Javaでは、これをループして、既存のリストに追加する新しいリストを作成します。私はこれをハスケルに翻訳することでかなり失われている。少し長い例で

+0

'removeone(a:as)= as:map(a :)(removeone as)' – user2407038

+0

@ user2407038回答としてコメントを投稿しないでください。 – chepner

+0

@ user2407038私は答えとして投稿しようとしていましたが、今は気分が悪いです。 –

答えて

3

:そして、ちょうどそのように、あなたの再帰的な場合があります。しかし、毎日のハスケルは再帰に関するものではなく、再帰的なパターンや問題の正確な定式化に関するものです。私はそれを持っている場合は、私は以下のソリューション

import Data.List (inits, tails) 

removeone :: [a] -> [[a]] 
removeone lst = zipWith (++) (inits lst) (tail (tails lst)) 

で終わるだろうこれは、明示的な再帰その後、もっとして2×より速く、より問題の製剤のように思えます。 tails [] = [[]]が「危険」機能を使用している場合、tailは安全です。軽度の症例はzipWith,initsおよびtailsである。

ジッパーを考慮し、それらのコモディーな性質を利用する(実際には驚くほど怖いわけではありません:)) 。

+2

このソリューションは、 'Data.List'の' inits'と 'tails'のチューニングされた実装の恩恵を受けていることに注目する価値があります。これらの議論は、「initsとtailの空間の複雑さは何ですか?」(http://stackoverflow.com/q/29393412/2751851)と「効率的なinits *」(http: /stackoverflow.com/q/27672585/2751851)。 – duplode

+0

これはすばらしい答えです!これは私を助け、私はこれを非常に理解しました! –

5

見てみましょうし、それを分割する方法を見つけ出す:あなたは既に推測したよう

> removeone [1,2,3,4] 
[[2,3,4],[1,3,4],[1,2,4],[1,2,3]] 

が、あなたは、単に上as(入力から最初の要素を除去した結果を)置きますフロント一部リストが、どのようなリストですか?

removeone (a:as) = as : ... 

さらに詳しく見ると、a == 1はそれぞれの先頭に表示されています。我々はそれを構築する方法を確認するためにそのアウト考慮してみましょう:

[[1,3,4],[1,2,4],[1,2,3]] == [1:[3,4],1:[2,4],1:[2,3]] 
          == map (1:) [[3,4],[2,4],[2,3]] 

2番目の引数はおなじみのはずです。それはあなたがremoveone [2,3,4]の結果が見えるように期待すべきものです。慣用的な再帰的な解決策は、@сhepnerで与えられる

removeone (a:as) = as : map (a:) (removeone as)