5

リストを受け取り、特定の要素 n で分割された 2 つのサブリストを返す次の関数があります。ただし、それを半分に分割するだけでよく、長さが奇数のリストは最初のサブリストが大きくなります

splitlist :: [a] -> Int -> ([a],[a])
splitlist [] = ([],[])
splitlist l@(x : xs) n | n > 0     = (x : ys, zs)
               | otherwise = (l, [])
    where (ys,zs) = splitlist xs (n - 1)

署名を [a] -> ([a],[a]) に変更する必要があることはわかっていますが、再帰を壊さないように、コードのどこに length(xs) のようなものを配置する必要がありますか?

4

2 に答える 2

10

実際のプログラムでは、おそらく使用する必要があります

splitlist :: [a] -> ([a], [a])
splitlist xs = splitAt ((length xs + 1) `div` 2) xs

(つまり、dreamcrashの回答に沿ったものです。)

ただし、学習目的で明示的に再帰的なソリューションを探している場合は、次のことを調べてください。

splitlist :: [a] -> ([a], [a])
splitlist xs = f xs xs where
    f (y : ys) (_ : _ : zs) =
        let (as, bs) = f ys zs
        in (y : as, bs)
    f (y : ys) (_ : []) = (y : [], ys)
    f ys [] = ([], ys)
于 2012-12-09T12:38:34.880 に答える
8

テイクアンドドロップを使用してそれを行うことができます:

splitlist :: [a] -> ([a],[a])
splitlist [] = ([],[])
splitlist l  = let half = (length(l) +1)`div` 2
               in (take half l, drop half l)

または、関数splitAtを利用できます。

splitlist list = splitAt ((length (list) + 1) `div` 2) list
于 2012-12-09T05:00:04.477 に答える