6

私は Haskell を独学していますが、正の整数n、 element y、およびリスト内のすべての要素の後にxs指定された要素を挿入するリストを取る関数 insert を定義するように求める本の質問に出くわしました。yn

パターンマッチングはおそらく良い方法だと思いますが、それが何を意味するのかはまだよく理解していません

insert :: Int -> Char -> [a] -> [a]
insert 0 y xs = xs
insert n y [] = []
insert n y (x:xs)

関数がどのように機能するかの例:

insert 2 'X' "abcdefghijk" = "abXcdXefXghXijXk"

この時点で基本的なケースに対処しましたが、ここから先に進む方法がわかりません。

何か案は?ありがとう

4

4 に答える 4

5

最後のケースでは、リストの n 要素を取得し、y のシングルトン リストを挿入し、リストの最初の n 要素を削除した後、関数を再帰的に呼び出した結果を追加します。

insert :: Int -> Char -> [a] -> [a]
insert 0 y xs = xs
insert n y [] = []
insert n y xs
 | length xs < n = xs
 | otherwise = take n xs ++ [y] ++ insert n y (drop n xs)
于 2012-09-30T07:59:57.210 に答える
4

ライブラリ関数を有利に使用することは問題ありません。

import Data.List

insertAtN n y xs = intercalate [y] . groups n $ xs
  where
    groups n xs = takeWhile (not.null) . unfoldr (Just . splitAt n) $ xs

もちろんChar、タイプのリストに挿入する[a]場合aChar、 Haskell ではリストのすべての要素が同じタイプであるためです。


これをより直接的なレベルで理解するのを助けるために、まずリストのコピーを作成することを見てみましょう:

copyList (x:xs) = x : copyList xs
copyList [] = []

ここで、コピーされる各要素にインデックス値を追加する (を再実装するzip xs [1..])と想像してください。

copyIdxList xs = go 1 xs where
  go i (x:xs) = (x,i) : go (i+1) xs
  go _ [] = []

各要素を処理するときにインデックス値を取得したので、それを使用して、たとえば、リストの 10 番目の各要素を2 回結果に入れることができます。

copyIdxTenthTwice xs = go 1 xs where
  go i (x:xs) | i==10 = (x,i) : (x,i) : go 1 xs
  go i (x:xs)         = (x,i) : go (i+1) xs
  go _ [] = []

私がこれでどこに行くのか分かりますか?を複製する代わりに、そこにx挿入できますy。また、インデックスを結果に入れる必要はありません。

于 2012-09-30T08:04:22.587 に答える
3

ゼロになるとカウントダウンしてリセットするヘルパー関数を作成できます。

insert :: Int -> a -> [a] -> [a]
insert n y xs = countdown n xs where
   countdown 0 xs = y:countdown n xs -- reset to original n
   countdown _ [] = []
   countdown m (x:xs) = x:countdown (m-1) xs

最後に挿入するときが来たら、どのような動作が必要ですか? countdown 0 xsここでは、前に配置することで、仕上げよりも挿入を優先しましたcountdown _ []。最後の挿入をスキップしたい場合、どのように書き直すことができますか?

使用例:

*Main> insert 3 '|' "Hello Mum, erm... can I borrow £20000 please?"
"Hel|lo |Mum|, e|rm.|.. |can| I |bor|row| £2|000|0 p|lea|se?|"
于 2012-09-30T08:01:37.160 に答える
1
ins n y xs = zip xs (cycle [1..n]) >>= f where
  f (x,k) = if k == n then [x,y] else [x] 

このzip部分は、リストの要素に巡回「インデックス」を付けます。たとえば、 forn = 3xs = "abcdefg"get[('a',1),('b',2)('c',3)('d',1)('e',2)('f',3)('g',1)]です。現在(これはリストの場合(>>=)と同じです) を使用して、サイクルの最後のインデックスがある場合を除いて、すべてのペアを元の要素にマップし直します: その場合、追加の分割要素も挿入します。concatMapfy

于 2012-09-30T21:41:24.700 に答える