diff --git a/src/Data/Array.js b/src/Data/Array.js index a31c6f90..57c74513 100644 --- a/src/Data/Array.js +++ b/src/Data/Array.js @@ -147,6 +147,20 @@ exports.findLastIndexImpl = function (just) { }; }; +exports.findMapWithIndexImpl = function (nothing) { + return function (isJust) { + return function (f) { + return function (xs) { + for (var i = 0, l = xs.length; i < l; i++) { + var y = f(i)(xs[i]); + if (isJust(y)) return y; + } + return nothing; + }; + }; + }; +}; + exports._insertAt = function (just) { return function (nothing) { return function (i) { diff --git a/src/Data/Array.purs b/src/Data/Array.purs index d3295941..bbfd70b4 100644 --- a/src/Data/Array.purs +++ b/src/Data/Array.purs @@ -60,6 +60,7 @@ module Data.Array , findMap , findIndex , findLastIndex + , findMapWithIndex , insertAt , deleteAt , updateAt @@ -499,6 +500,25 @@ foreign import findLastIndexImpl -> Array a -> Maybe Int +-- | Find the first element which satisfies a predicate mapping. +-- | The mapping function has access to both index and value at the index. +-- | +-- | ```purescript +-- | findMapWithIndex (\i x -> if contains (Pattern "b") x then Just {i,x} else Nothing) ["a", "bb", "b", "d"] = Just { i: 1, x: "bb" } +-- | findMapWithIndex (\i x -> if contains (Pattern "x") x then Just {i,x} else Nothing) ["a", "bb", "b", "d"] = Nothing +-- | ``` +-- | +findMapWithIndex :: forall a b. (Int -> a -> Maybe b) -> Array a -> Maybe b +findMapWithIndex = findMapWithIndexImpl Nothing isJust + +foreign import findMapWithIndexImpl + :: forall a r + . (forall b. Maybe b) + -> (forall b. Maybe b -> Boolean) + -> (Int -> a -> Maybe r) + -> Array a + -> Maybe r + -- | Insert an element at the specified index, creating a new array, or -- | returning `Nothing` if the index is out of bounds. -- | diff --git a/test/Test/Data/Array.purs b/test/Test/Data/Array.purs index 9325c0f8..c3f8f22e 100644 --- a/test/Test/Data/Array.purs +++ b/test/Test/Data/Array.purs @@ -467,6 +467,10 @@ testArray = do , [4,0,0,1,25,36,458,5842,23757] ] + log "findMapWithIndex should return the value returned for the first item for which the given function returned a Just" + assert $ (A.findMapWithIndex (\i x -> if x /= 1 then Just { index: i, value: x } else Nothing) [1, 2, 1]) == Just { index: 1, value: 2 } + assert $ (A.findMapWithIndex (\i x -> if x == 3 then Just { index: i, value: x } else Nothing) [1, 2, 1]) == Nothing + nea :: Array ~> NEA.NonEmptyArray nea = unsafePartial fromJust <<< NEA.fromArray