Haskell中如何优雅实现向双列表组成的元组按条件填充元素
实现方案
你需要的功能本质是将列表按指定谓词拆分为两个子列表,Haskell有多种符合函数式风格的实现方案:
1. 最简洁的标准库方案
直接使用Data.List模块的partition函数,一行即可完成需求:
import Data.List (partition) type One = [Int] type Two = [Int] bar :: Int -> Bool bar = undefined -- 替换为你的判断逻辑实现 foo :: [Int] -> (One, Two) foo = partition bar
partition的函数签名为(a -> Bool) -> [a] -> ([a], [a]),返回的元组第一个元素是所有满足谓词bar的元素列表,第二个是所有不满足条件的元素列表,完全匹配你的需求。
2. 手动递归实现
如果需要自行实现逻辑,优先使用模式匹配处理列表结构,避免null、tail这类空列表下会抛出异常的部分函数:
type One = [Int] type Two = [Int] bar :: Int -> Bool bar = undefined foo :: [Int] -> (One, Two) foo [] = ([], []) foo (x:xs) | bar x = let (ones, twos) = foo xs in (x : ones, twos) | otherwise = let (ones, twos) = foo xs in (ones, x : twos)
逻辑说明:先递归处理剩余列表拿到拆分结果元组,再根据当前元素的判断结果,把元素追加到对应列表的头部即可。
3. 折叠实现(无显式递归的函数式写法)
也可以用右折叠实现,不用手动写递归逻辑:
foo :: [Int] -> (One, Two) foo = foldr step ([], []) where step x (ones, twos) | bar x = (x : ones, twos) | otherwise = (ones, x : twos)
内容的提问来源于stack exchange,提问作者CoffeeKid
相关产品推荐
相关产品推荐

