反向列表顺序而不增加复杂性

时间:2015-02-07 20:44:55

标签: algorithm list haskell time-complexity

我想要filter的替代方案,而不是丢弃错误的案例,将它们放在一个单独的地方。我想出了下面的内容,但不幸的是它颠倒了这个清单。

显然我可以将x附加到ys或zs而不是cons,但这会大大增加复杂性。

有没有办法在不增加复杂性的情况下保持秩序?

splitBy :: (a -> Bool) -> [a] -> ([a],[a])
splitBy f xs = splitBy' f xs ([],[])
            where
                splitBy' :: (a -> Bool) -> [a] -> ([a],[a]) -> ([a],[a])
                splitBy' _   []   result  = result
                splitBy' f (x:xs) (ys,zs) = if f x then splitBy' f xs (x:ys,zs)
                                                   else splitBy' f xs (ys,x:zs)

1 个答案:

答案 0 :(得分:3)

正如其他人所说,该函数被称为partition,它的工作原理如下

partition :: (a -> Bool) -> [a] -> ([a], [a])
partition f = foldr (\x ~(yes,no) ->
                         if f x
                         then (x:yes,no)
                         else (yes,x:no))
                    ([], [])

除了真实版本添加显式xs参数,可能是为了帮助融合规则正常工作。如果那种时髦的懒惰模式匹配让你感到紧张,你可以这样写:

partition f = foldr (\x r ->
                         if f x
                         then (x:fst r,snd r)
                         else (fst r,x:snd r))
                    ([], [])

如果foldr看起来很神秘,你可以这样做:

partition f [] = ([], [])
partition f (x:xs)
  | f x       = (x:fst r, snd r)
  | otherwise = (fst r, x:snd r)
  where r = partition f xs