on master help sign in
Merge pull request #586 from hdgarrood/dict-filter

Add Dict and Set filtering functions

commit3889b1177f40f41e623bbea8a2bb6724678dd632 authorEvan Czaplicki <info@elm-lang.org> dateWed 16 Apr 2014, 15:42 (13 years ago) parent525acc5db1f2ec
4 files changed+90−4
libraries/Dict.elm+23−4 libraries/Set.elm+12 tests/elm/Test/Dict.elm+29 tests/elm/Test/Set.elm+26
libraries/Dict.elm+23−4
@@ -1,6 +1,8 @@
11module Dict (empty,singleton,insert,update
22 ,lookup,findWithDefault
33 ,remove,member
4+ ,filter
5+ ,partition
46 ,foldl,foldr,map
57 ,union,intersect,diff
68 ,keys,values
@@ -26,7 +28,7 @@ Insert, remove, and query operations all take *O(log n)* time.
2628@docs keys, values, toList, fromList
2729
2830# Transform
29−@docs map, foldl, foldr
31+@docs map, foldl, foldr, filter, partition
3032
3133-}
3234
@@ -327,9 +329,7 @@ union t1 t2 = foldl insert t2 t1
327329{-| Keep a key-value pair when its key appears in the second dictionary.
328330Preference is given to values in the first dictionary. -}
329331intersect : Dict comparable v -> Dict comparable v -> Dict comparable v
330−intersect t1 t2 =
331− let combine k v t = if k `member` t2 then insert k v t else t
332− in foldl combine empty t1
332+intersect t1 t2 = filter (\k _ -> k `member` t2) t1
333333
334334{-| Keep a key-value pair when its key does not appear in the second dictionary.
335335Preference is given to the first dictionary. -}
@@ -351,3 +351,22 @@ toList t = foldr (\k v acc -> (k,v) :: acc) [] t
351351{-| Convert an association list into a dictionary. -}
352352fromList : [(comparable,v)] -> Dict comparable v
353353fromList assocs = List.foldl (\(k,v) d -> insert k v d) empty assocs
354+
355+{-| Keep a key-value pair when it satisfies a predicate. -}
356+filter : (comparable -> v -> Bool)
357+ -> Dict comparable v
358+ -> Dict comparable v
359+filter p =
360+ let add k v t = if p k v then insert k v t else t
361+ in foldl add empty
362+
363+{-| Partition the Dict according to a predicate. The first Dict contains all
364+key-value pairs which satisfy it; the second contains the rest. -}
365+partition : (comparable -> v -> Bool)
366+ -> Dict comparable v
367+ -> (Dict comparable v, Dict comparable v)
368+partition p =
369+ let add k v (t1, t2) = if p k v
370+ then (insert k v t1, t2)
371+ else (t1, insert k v t2)
372+ in foldl add (empty, empty)
libraries/Set.elm+12
@@ -2,6 +2,7 @@
22module Set (empty,singleton,insert,remove
33 ,member
44 ,foldl,foldr,map
5+ ,filter,partition
56 ,union,intersect,diff
67 ,toList,fromList
78 ) where
@@ -88,3 +89,14 @@ foldr f b s = Dict.foldr (\k _ b -> f k b) b s
8889{-| Map a function onto a set, creating a new set with no duplicates. -}
8990map : (comparable -> comparable') -> Set comparable -> Set comparable'
9091map f s = fromList (List.map f (toList s))
92+
93+{-| Create a new set consisting only of elements which satisfy a predicate. -}
94+filter : (comparable -> Bool) -> Set comparable -> Set comparable
95+filter p = Dict.filter (\k _ -> p k)
96+
97+{-| Create two new sets; the first consisting of elements which satisfy a
98+predicate, the second consisting of elements which do not. -}
99+partition : (comparable -> Bool)
100+ -> Set comparable
101+ -> (Set comparable, Set comparable)
102+partition p = Dict.partition (\k _ -> p k)
tests/elm/Test/Dict.elmnew file+29
@@ -0,0 +1,29 @@
1+module Test.Dict (tests) where
2+
3+import Dict
4+import List
5+import Char
6+
7+import ElmTest.Assertion (..)
8+import ElmTest.Test (..)
9+
10+parseDigit : Char -> Int
11+parseDigit ch = Char.toCode ch - 48
12+
13+dict1List = [(1,'1'),(2,'2'),(3,'3'),(5,'5')]
14+
15+dict1 : Dict Int Char
16+dict1 = Dict.fromList dict1List
17+
18+dict1Part1 : Dict Int Char
19+dict1Part1 = Dict.fromList (take 2 dict1List)
20+
21+dict1Part2 : Dict Int Char
22+dict1Part2 = Dict.fromList (drop 2 dict1List)
23+
24+tests : [Test]
25+tests =
26+ let
27+ filterTests = [assertEqual dict1Part2 <| filter (\v -> parseDigit v > 2) dict1]
28+ partitionTests = [assertEqual (dict1Part1, dict1Part2) <| partition (\v -> v != '3' && v != '5') dict1]
29+ in List.concat [filterTests, partitionTests]
tests/elm/Test/Set.elmnew file+26
@@ -0,0 +1,26 @@
1+module Test.Set (tests) where
2+
3+import Set
4+import List
5+
6+import ElmTest.Assertion (..)
7+import ElmTest.Test (..)
8+
9+set : Set
10+set = Set.fromList [1..100]
11+
12+setPart1 : Set
13+setPart1 = Set.fromList [1..50]
14+
15+setPart2 : Set
16+setPart2 = Set.fromList [51..100]
17+
18+pred : Int -> Bool
19+pred x = x <= 50
20+
21+tests : [Test]
22+tests =
23+ let
24+ filterTests = [assertEqual setPart1 <| filter pred set]
25+ partitionTests = [assertEqual (setPart1, setPart2) <| partition pred set]
26+ in List.concat [partitionTests, filterTests]