Commits

Bryan O'Sullivan committed 469a86e

Implement findIndices.

  • Participants
  • Parent commits e547d46

Comments (0)

Files changed (3)

File Data/Text.hs

     -- * Indexing
     , index
     , findIndex
-    -- , findIndices
+    , findIndices
     , elemIndex
     -- , elemIndices
     -- , count
 index t n = S.index (stream t) n
 {-# INLINE index #-}
 
--- | The 'findIndex' function takes a predicate and a 'Text' and
--- returns the index of the first element in the 'Text'
--- satisfying the predicate.
+-- | /O(n)/ The 'findIndex' function takes a predicate and a 'Text'
+-- and returns the index of the first element in the 'Text' satisfying
+-- the predicate. This function is subject to fusion.
 findIndex :: (Char -> Bool) -> Text -> Maybe Int
 findIndex p t = S.findIndex p (stream t)
 {-# INLINE findIndex #-}
 
+-- | The 'findIndices' function extends 'findIndex', by returning the
+-- indices of all elements satisfying the predicate, in ascending
+-- order. This function is subject to fusion.
+findIndices :: (Char -> Bool) -> Text -> [Int]
+findIndices p t = S.findIndices p (stream t)
+{-# INLINE findIndices #-}
+
 -- | /O(n)/ The 'elemIndex' function returns the index of the first
 -- element in the given 'Text' which is equal to the query element, or
--- 'Nothing' if there is no such element.
+-- 'Nothing' if there is no such element. This function is subject to
+-- fusion.
 elemIndex :: Char -> Text -> Maybe Int
 elemIndex c t = S.elemIndex c (stream t)
 

File Data/Text/Fusion.hs

     , find
     , index
     , findIndex
+    , findIndices
     , findIndexOrEnd
     , elemIndex
 
 -- returns the index of the first element in the stream
 -- satisfying the predicate.
 findIndex :: (Char -> Bool) -> Stream Char -> Maybe Int
-findIndex p (Stream next s0 _len) = loop_findIndex 0 s0
+findIndex p s = case findIndices p s of
+                  (i:_) -> Just i
+                  _     -> Nothing
+{-# INLINE [0] findIndex #-}
+
+-- | The 'findIndices' function takes a predicate and a stream and
+-- returns all indices of the elements in the stream
+-- satisfying the predicate.
+findIndices :: (Char -> Bool) -> Stream Char -> [Int]
+findIndices p (Stream next s0 _len) = loop_findIndex 0 s0
   where
     loop_findIndex !i !s = case next s of
-      Done                   -> Nothing
+      Done                   -> []
       Skip    s'             -> loop_findIndex i     s' -- hmm. not caught by QC
-      Yield x s' | p x       -> Just i
+      Yield x s' | p x       -> i : loop_findIndex (i+1) s'
                  | otherwise -> loop_findIndex (i+1) s'
-{-# INLINE [0] findIndex #-}
+{-# INLINE [0] findIndices #-}
 
 -- | The 'findIndexOrEnd' function takes a predicate and a stream and
 -- returns the index of the first element in the stream

File tests/Properties.hs

 prop_index x s       = x < L.length s && x >= 0 ==>
                        (L.!!) s x == T.index (pack s) x
 prop_findIndex p     = L.findIndex p `eqP` T.findIndex p
+prop_findIndices p   = L.findIndices p`eqP` T.findIndices p
 prop_elemIndex c     = L.elemIndex c `eqP` T.elemIndex c
 prop_zipWith c s     = L.zipWith c s `eqP` (unpack . T.zipWith c (pack s))
 
 
   ("prop_index", mytest prop_index),
   ("prop_findIndex", mytest prop_findIndex),
+  ("prop_findIndices", mytest prop_findIndices),
   ("prop_elemIndex", mytest prop_elemIndex),
   ("prop_zipWith", mytest prop_zipWith)
   ]