Haskell 我如何创建一个;计数“;滤器
我有一个对列表,我需要一个只保留第一个对成员至少出现两次的元素的过滤器:Haskell 我如何创建一个;计数“;滤器,haskell,Haskell,我有一个对列表,我需要一个只保留第一个对成员至少出现两次的元素的过滤器: someFilter :: Eq a => [(a, b)] -> [(a, b)] someFilter [("a",1),("a",2),("b",1)] `shouldBe` [("a",1),("a",2)] -- "a" occurs in two pairs, retain both someFilter [("a",1),("a",2),("b",1),("b",2)
someFilter :: Eq a => [(a, b)] -> [(a, b)]
someFilter [("a",1),("a",2),("b",1)]
`shouldBe` [("a",1),("a",2)] -- "a" occurs in two pairs, retain both
someFilter [("a",1),("a",2),("b",1),("b",2)]
`shouldBe` [("a",1),("a",2),("b",1),("b",2)] -- "a" and "b" occur twice
someFilter [("a",1),("b",2),("c",1),("d",2)]
`shouldBe` [] -- no string occurs twice
我不确定如何实现这样一个过滤器。通常的
过滤器
仅按元素工作。如何编写someFilter
?您可以首先按元组的第一个元素对元组进行分组,然后对至少有两个元素的组进行合并。此解决方案不是O(n^2),而是施加了Ord
约束
import Data.List (groupBy, sortBy)
import Data.Function (on)
import Data.Ord (comparing)
someFilter :: Ord a => [(a, b)] -> [(a, b)]
someFilter = concat
. filter ((>= 2) . length)
. groupBy ((==) `on` fst)
. sortBy (comparing fst)
您可以首先按元组的第一个元素对元组进行分组,然后对至少有两个元素的组进行合并。此解决方案不是O(n^2),而是施加了
Ord
约束
import Data.List (groupBy, sortBy)
import Data.Function (on)
import Data.Ord (comparing)
someFilter :: Ord a => [(a, b)] -> [(a, b)]
someFilter = concat
. filter ((>= 2) . length)
. groupBy ((==) `on` fst)
. sortBy (comparing fst)
正如前面提到的另一个答案,您需要对列表进行分组。最明显的候选方法是在Frerich解决方案中使用
Data.List.groupBy
,然而,我经常发现创建地图更容易(您不需要排序)
导入符合条件的数据。映射为M
someFilter xs=M.keys$M.filter(>=1)
(M.fromList(+)[(x,1)|(x,))另一个答案已经说过,您需要对列表进行分组。最明显的候选方法是在Frerich解决方案中使用Data.List.groupBy
,然而,我经常发现创建地图更容易(您不需要排序)
导入符合条件的数据。映射为M
someFilter xs=M.keys$M.filter(>=1)
(M.fromList(+)[(x,1)|(x,))如果列表1=[((a,1),((a,2),((b,1),((b,2)]
?祝你好运,玩得开心。明确回答:这甚至不是一个问题。我们不知道你被困在哪里。@thefourtheye:[((a,1),((a),2),(b,1),((b),2)]@gspr我试图更好地解释这个问题。我实际上需要找到所有第一项出现的元组,如果列表1=[((“a”,1),(“a”,2),(“b”,1),(“b”,2)]
?祝你好运,玩得开心。明确回答:这甚至不是一个问题。我们不知道你被困在哪里。@theourtheye:[(“a”,1),(“a”,2),(“b”,1),(“b”,2)]@gspr我试图更好地解释这个问题。我实际上需要找到所有第一项出现次数超过一次的元组。我更喜欢not.null.drop 2
到(>=2).length
,因为后者访问所有列表,而前者不比第三个元素更深。(这并不重要——原著可以说更可读)@chi,出于列表融合的目的(在这里不相关),最好使用atLeastLength nxs=foldr go(=0)xsn,其中{go uu0=True;go ck=c(k-1)}
,不幸的是,这是最不清楚的。我更喜欢not.null.drop 2
到(>=2).length
,因为后者访问所有列表,而前者不比第三个元素更深。(这并不重要——可以说原始元素更可读)@chi,用于列表融合目的(此处不相关),最好使用类似于atLeastLength n xs=foldr go(=0)xs n的内容,其中{go uu0=True;go c k=c(k-1)}
,不幸的是,这是最不清楚的。