Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/google-apps-script/5.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Haskell 我如何创建一个;计数“;滤器_Haskell - Fatal编程技术网

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)}
,不幸的是,这是最不清楚的。