繁体   English   中英

将列表拆分为Haskell中的子列表

[英]Splitting list into sublists in Haskell

如何将列表拆分为2个子列表,其中第一个子列表包括从初始列表的开头到等于第一个元素的元素,第二个子列表包含其他元素? 我必须在不使用Prelude函数的情况下解决这个问题。

我的基本解决方案是:

partSameElems :: [a] -> ([a],[a])
partSameElems [] = ([],[])
partSameElems (x:xs) = fstList (x:xs) scdList (x:xs)
    where 
        fstList (x:y:xs) = if x == y then x:y:fstList xs {- I need to do Nothing in else section? -} 
        scdList (x:xs) = x:scdList xs

例如: [3,3,3,3,2,1,3,3,6,3] -> ([3,3,3,3], [2,1,3,3,6,3])

现在我可以提供我的解决方案版本:

partSameElems :: Eq a => [a] -> ([a],[a])
partSameElems [] = ([],[])
partSameElems (x:xs) = (fstList (x:xs), scdList (x:xs))
where
    fstList [] _ = []
    fstList (x:xs) el = if x == el then x:fstList xs el else []
    scdList [] _ = []
    scdList (x:xs) el = if x /= el then (x:xs) else  scdList xs el

如果你不尝试两次通过,这会更容易。

parSameElems [] = ([], [])
parSameElems lst = (reverse revxs, ys)
  where (revxs, ys) = accum [] lst
        accum xs [y] = ((y:xs), [])
        accum xs (y1:y2:ys) | y1 == y2 = accum (y1:xs) (y2:ys)
                            | otherwise = ((y1:xs), (y2:ys))

不确定你可以在where子句中使用guard语法。 你也必须自己实现反向,因为你不能使用Prelude,但这很容易。

注意:我实际上没有运行它。 确保您尝试调试它。

另外,不要自己编写类型签名。 让ghci告诉你。 你第一次尝试就弄错了。

我认为“不使用Prelude功能”意味着它具有教育意义。 考虑到它对List数据的操纵,可能旨在处理递归。 所以让我们强调一下

当输入和输出类型相同时,递归算法更容易表达。 让我们更确切地说,而不是列表[3,3,3,3,2,1,3,3,6,3] ,您的输入数据由

  • 前面的清单,但在这个阶段它是空的
  • 剩下的,在这个阶段等于输入[3,3,3,2,1,3,3,6,3]
  • 然后递归输入([],[3,3,3,2,1,3,3,6,3])

中心函数的类型是([a],[a]) -> ([a],[a])

现在,每个递归步骤将采用余数的前面元素,并将if放在前面列表中或停止递归(您到达最终状态并可以返回结果)

module SimpleRecursion where
moveInFront :: (Eq a) => ([a],[a]) -> ([a],[a])
moveInFront (xs    , []   ) =                ( xs    , [])
moveInFront ([]    , y:ys ) =                moveInFront ( y:[]  , ys)
moveInFront (x:xs  , y:ys ) = if x == y then moveInFront ( y:x:xs  , ys) 
                                        else (x:xs, y:ys)

partSameElems :: (Eq a) => [a] -> ([a],[a])
partSameElems a = moveInFront ([],a)

我们这里有一个经典的递归方案,有 - 停止条件(x / = y) - 递归子句 - 覆盖琐碎的案例

注意: - 写y:x:xs实际上反转了前面的列表但由于所有值都相等,结果是正确的请不要在实际程序的代码中做那种技巧,它最终会回来咬你 -该函数仅适用于Equatable数据列表(Eq a) =>因为递归/停止条件是相等测试==

另一种实现方式可以

partition [] = ([],[])
partition xa@(x:xs) = (f,s)
              where
                   f = takeWhile (==x) xa
                   s = drop (length f) xa

应该清楚它的作用。

> partition [3,3,3,3,2,1,3,3,6,3]
([3,3,3,3],[2,1,3,3,6,3])

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM