haskell - 根据条件对列表进行分区的功能 - Haskell
问题描述
我正在学习 Haskell,我正在做的一个练习是创建一个函数,该函数根据函数的返回值将列表划分为三个列表,以便为等于 1 的函数值获得第一个子列表,函数值的第二个子列表为 2,第三个子列表包含其他所有内容。
函数声明读取
partition3 :: (a -> Int) -> [a] -> ([a], [a], [a])
partition3 _ [] = []
作为一个入门示例,请考虑
partition3 (\x -> mod x 5) [1..10] = ([1,6], [2,7], [3,4,5,8,9,10])
现在,我已经编写了函数filterAny
, isSuitable
, removeIf
, isNotSuitable
。完整代码如下:
filterAny :: [a -> Bool] -> [a] -> [a]
filterAny _ [] = []
filterAny ps (x:xs)
| isSuitable ps x = x : filterAny ps xs
| otherwise = filterAny ps xs
isSuitable :: [a -> Bool] -> a -> Bool
isSuitable [] _ = False
isSuitable (p:ps) v
| p v = True
| otherwise = isSuitable ps v
removeIf :: [a -> Bool] -> [a] -> [a]
removeIf _ [] = []
removeIf ps (x:xs)
| isNotSuitable ps x = x : removeIf ps xs
| otherwise = removeIf ps xs
isNotSuitable :: [a -> Bool] -> a -> Bool
isNotSuitable [] _ = True
isNotSuitable (p:ps) v
| p v = False
| otherwise = isNotSuitable ps v
使用这些函数,我们可以获得所需的输出partition3
:
filterAny [(\x -> mod x 5 == 1)] [1..10] = [1,6]
filterAny [(\x -> mod x 5 == 2)] [1..10] = [2,7]
removeIf [even, (\x -> x > 5)] [1..10] = [3,4,5,8,9,10]
不幸的是,我仍然没有想出如何编写这个函数来输出([1,6], [2,7], [3,4,5,8,9,10])
解决方案
考虑“创建”类型值的一种高级方法(a,b,c)
是考虑必须“构造”它的方式,例如构造函数。在这种情况下,(a,b,c)
有一个构造函数,(_,_,_)
. 因此,您需要考虑要放入第一个插槽的东西,要放入第二个插槽的东西,以及要放入第三个插槽的东西……您就完成了。
所以让我们这样概述我们的功能:
partition3 :: (a -> Int) -> [a] -> ([a], [a], [a])
partition3 f xs = (_, _, _)
我们知道我们的最终答案是形式(_,_,_)
,其中“空白”包含我们想要放入元组的每个项目。让我们给每个空白一个有用的名字。
partition3 :: (a -> Int) -> [a] -> ([a], [a], [a])
partition3 f xs = (equalsOne, equalsTwo, theRest)
where
equalsOne = ???
equalsTwo = ???
theRest = ???
现在您只需要equalsOne
成为与您想要的属性相匹配的项目xs
,等等。属性equalsOne
是“一个值x
匹配,如果当您应用f
它时,它给出了1
”。所以让我们用filterAny
:
partition3 :: (a -> Int) -> [a] -> ([a], [a], [a])
partition3 f xs = (equalsOne, equalsTwo, theRest)
where
equalsOne = filterAny [\x -> f x == 1] xs
equalsTwo = ???
theRest = ???
在这里,我们过滤xs
任何项目,如果你申请f
它,给出1
.
你能想出方法来实现equalsTwo
和theRest
,沿着同样的路线吗?
推荐阅读
- matlab - 无法从文本文件中导入数字
- amazon-web-services - AWS 无服务器 API 请求
- javascript - 如何让这段代码一次移动一个班级
- c# - 运行时 C# 创建列表
其中 T 是未知的,如 List - java - 如何在 Java 中动态声明数组的形状?
- python - 计算距离最低的曼哈顿距离返回类别
- python - 应用程序 spyder 启动可能会产生错误窗口
- swift - Swift 4 -- 在单个泛型函数中使用带有 `random(:in)` 的浮点类型和带有 `random(:in)` 的整数类型
- android - Room:“错误:不确定如何将 Cursor 转换为此方法的返回类型”。构建正确的转换器
- spring-boot - 自己的 HttpTraceRepository