Module

Data.Array.Extra

Package
purescript-arrays-extra
Repository
flip111/purescript-arrays-extra

Some specialized functions can be found here.

#sortByMultiple Source

sortByMultiple :: forall a. Array (a -> a -> Ordering) -> Array a -> Array a

Sort by multiple comparison functions. Similar to SQL where you can specificy multiple columns with ASC and DESC. When a comparison function gives EQ the next one is tried.

Other functions don't have a Multiple variant such as sortOnByMultiple. Because the implementation of this function is so simple it serves as example function. sortByMultiple comps xs = sortBy (fold comps) xs

let datas = [{a: 2, b: 4}, {a: 3, b: 4}, {a: 2, b: 5}, {a: 1, b: 5}]
    a {a: a1} {a: a2} = compare a1 a2
    b {b: b1} {b: b2} = compare b1 b2 -- use flip for DESC, or alternatively: compare b2 b1
in  sortByMultiple [a, flip b] datas = [{a: 1, b: 5}, {a: 2, b: 5}, {a: 2, b: 4}, {a: 3, b: 4}]

#sortOn Source

sortOn :: forall a b. Ord b => (a -> b) -> Array a -> Array a

Sort a list by a projection.

sortOn (\x -> if x == "dog" then 2 else 1) ["apple", "dog", "kiwi"] = ["apple", "kiwi", "dog"]

#sortOn' Source

sortOn' :: forall a b. Ord b => (a -> b) -> Array a -> Array a

Sort a list by a projection. This version of sortOn uses the decorate-sort-undecorate paradigm or Schwartzian transform. Which means the projection for each entry will only be computed once at the cost of creating more data structures. You will have to benchmark your specific situation to find out whether sortOn or sortOn' is faster.

sortOn' (\x -> if x == "dog" then 2 else 1) ["apple", "dog", "kiwi"] = ["apple", "kiwi", "dog"]

#sortOnBy Source

sortOnBy :: forall a b. (a -> b) -> (b -> b -> Ordering) -> Array a -> Array a

Sort a list by a projection and sort by a given comparison function.

sortOnBy (\x -> if x == "dog" then 2 else 1) compare ["apple", "dog", "kiwi"] = ["apple", "kiwi", "dog"]

#sortOnBy' Source

sortOnBy' :: forall a b. (a -> b) -> (b -> b -> Ordering) -> Array a -> Array a

Sort a list by a projection and sort by a given comparison function. This version of sortOnBy uses the decorate-sort-undecorate paradigm or Schwartzian transform. Which means the projection for each entry will only be computed once at the cost of creating more data structures. You will have to benchmark your specific situation to find out whether sortOnBy or sortOnBy' is faster.

sortOnBy' (\x -> if x == "dog" then 2 else 1) compare ["apple", "dog", "kiwi"] = ["apple", "kiwi", "dog"]

#sortOnByMaybe Source

sortOnByMaybe :: forall a b. (a -> Maybe b) -> (b -> b -> Ordering) -> Array a -> Array a

Sort a list by a projection and sort by a given comparison function. When the projection returns Nothing those items will be placed last. Useful if your Array contains items with missing data to sort on

sortOnByMaybe (\x -> if x == "dog" then Just 2 else Just 1) compare ["apple", "dog", "kiwi"] = ["apple", "kiwi", "dog"]

#sortOnByMaybe' Source

sortOnByMaybe' :: forall a b. (a -> Maybe b) -> (b -> b -> Ordering) -> Array a -> Array a

Sort a list by a projection and sort by a given comparison function. When the projection returns Nothing those items will be placed last. Useful if your Array contains items with missing data to sort on This version of sortOnByMaybe uses the decorate-sort-undecorate paradigm or Schwartzian transform. Which means the projection for each entry will only be computed once at the cost of creating more data structures. You will have to benchmark your specific situation to find out whether sortOnByMaybe or sortOnByMaybe' is faster.

sortOnByMaybe' (\x -> if x == "dog" then Just 2 else Just 1) compare ["apple", "dog", "kiwi"] = ["apple", "kiwi", "dog"]

#partitionEithers Source

partitionEithers :: forall a l r. (a -> Either l r) -> Array a -> { left :: Array l, right :: Array r }

Partitions an array of Either into two arrays. All the Left elements are put, in order, into the left field of the output record. Similarly the Right elements are put into the right field of the output record. Note that this function is an alias for partitionMap from Data.Filterable. The function is included in this library for people who prefer this name for the function as they might be used to it from haskell

partitionEithers (\a -> if a > 2 then Left a else Right a) [1,2,3,4] == {left: [1,2], right: [3,4]}

#combinations Source

combinations :: forall a. Int -> Array a -> Maybe (Array (NonEmptyArray a))

Get all combinations when drawing n elements from an array. n must be greater than 0 and not greater than the length of the array otherwise this function returns Nothing

let products = [{product: "bread", amount: 1}, {product: "cheese", amount: 2}, {product: "bread", amount: 3}]
combinations 2 [1,2,3] -> Just [[1,2], [2,3], [1,3]]

#interleave Source

interleave :: forall a. Array (Array a) -> Array a

Takes an element from each array in turn to produce a new array.

interleave [[1,2], [3,4]] = [1,3,2,4]
concat     [[1,2], [3,4]] = [1,2,3,4]

Re-exports from Data.Foldable.Extra

#sameElements Source

sameElements :: forall a f. Foldable f => Eq a => f a -> f a -> Boolean

Checks if two arrays have exactly the same elements. The order of elements does not matter.

sameElements ["A", "B", "B"] ["B", "A", "B"] == true
sameElements ["A", "B", "B"] ["A", "B"] == false

#partitionMaybe Source

partitionMaybe :: forall a b f. Foldable f => (a -> Maybe b) -> f a -> { no :: Array a, yes :: Array b }

Try to make a projection from an array. Return an array with the projection and the original array with the elements removed.

partitionMaybe (\x -> if x == "dog" then Just "cat" else Nothing) ["apple", "dog", "kiwi"] == { no: ["apple", "kiwi"], yes: ["cat"] }

#occurrencesMap Source

occurrencesMap :: forall a f. Foldable f => Ord a => f a -> Map a Int

Count the amount of times a value occurs in an array. Requires an Ord instance for Map. This function should be faster than occurrences

occurrencesMap ["A", "B", "B"] == Map.fromList [Tuple "A" 1, Tuple "B" 2]

#occurrences Source

occurrences :: forall a f. Eq a => Foldable f => f a -> Array (Tuple a Int)

Count the amount of times a value occurs in an array. Mostly useful for when you can not define an Ord instance

occurrences ["A", "B", "B"] == [Tuple "A" 1, Tuple "B" 2]

#mapMaybeAny Source

mapMaybeAny :: forall f a. Foldable f => (a -> Maybe a) -> f a -> Maybe (Array a)

Map an array conditionally, only return the array when at least one element was mapped. Elements that are not mapped will keep the old value.

mapMaybeAny (\_ -> Nothing) [1,2,3] == Nothing
mapMaybeAny (\x -> if x == 2 then Just 99 else Nothing) [1,2,3] == Just [1,99,3]

#mapEither Source

mapEither :: forall a b c f. Foldable f => (a -> Either c b) -> f a -> Either (Array c) (Array b)

Map with a function that yields Either. Only succeeding when all elements where mapped to Right. Hint: if you don't care about collecting all the Left's (error conditions) and you are looking for a function like forall a b c. (a -> Either c b) -> Array a -> Either c (Array b) then use traverse from Data.Traversable.

#groupMaybeMap Source

groupMaybeMap :: forall a b c f. Foldable f => Eq b => (a -> Maybe b) -> (a -> c) -> f a -> Array (Tuple b (NonEmptyArray c))

Similar to groupMaybe, adds the ability to map over the thing being grouped. Useful for removing data that was only there to do the grouping.

groupMaybeMap (\x -> Just $ if even x then "even" else "odd") (*3) [1,2,3] == [(Tuple "odd" [3,9]), (Tuple "even" [6])]
groupMaybeMap f identity xs = groupMaybe f xs

#groupMaybe Source

groupMaybe :: forall f a b. Foldable f => Eq b => (a -> Maybe b) -> f a -> Array (Tuple b (NonEmptyArray a))

Similar to group, adds the ability to group by a projection. The projection is returned as the first argument of the Tuple.

groupMaybe (\x -> Just $ if even x then "even" else "odd") [1,2,3] == [(Tuple "odd" [1,3]), (Tuple "even" [2])]

#anyPredicate Source

anyPredicate :: forall f a. Foldable f => f (a -> Boolean) -> (a -> Boolean)

Combines multiple predicates into one. Only one has to match.

let preds = anyPredicate [(_ > 5), (_ > 10)]
all preds [5,10] == true
all preds [1,5,10] == false
any preds [1,5] == true
any preds [1] == false

#allPredicate Source

allPredicate :: forall f a. Foldable f => f (a -> Boolean) -> (a -> Boolean)

Combines multiple predicates into one. All have to match.

let preds = allPredicate [(_ > 5), (_ > 10)]
all preds [10,20] == true
all preds [5,10,20] == false
any preds [1,5,10] == true
any preds [1,5] == false

Re-exports from Data.Semigroup.Foldable.Extra

#mapAny Source

mapAny :: forall a f. Traversable1 f => (a -> Maybe a) -> f a -> Maybe (f a)

Map an array conditionally, only return the array when at least one element was mapped. Elements that are not mapped will keep the old value.

Hint: mapAll can be found in Data.Semigroup.Traversable.Extra

mapAny (\_ -> Nothing) (Data.Array.NonEmpty.cons' 1 [2, 3]) == Nothing
mapAny (\x -> if x == 2 then Just 99 else Nothing) (Data.Array.NonEmpty.cons' 1 [2, 3]) == Data.Array.NonEmpty.fromArray [1,99,3]

Not that in the second example the Just is implicit.

Re-exports from Data.Traversable.Extra

#mapModify Source

mapModify :: forall a f. Traversable f => (a -> { new :: a, old :: a }) -> f a -> Tuple (Array a) (f a)

Like map but extracts the replaced values into an array. Allows modification of the replaced values as well.

#mapMaybeWriteModify Source

mapMaybeWriteModify :: forall a f. Traversable f => (a -> Maybe { new :: a, old :: a }) -> f a -> Tuple (Array a) (f a)

Same as mapMaybeWrite but allows modification of replaced values before returning them. Useful when the old and new values need to be linked to each other.

#mapMaybeWrite Source

mapMaybeWrite :: forall a f. Traversable f => (a -> Maybe a) -> f a -> Tuple (Array a) (f a)

Conditionally map the function over the the functor. Returns a Tuple with the new functor and the replaced values.

#mapAll Source

mapAll :: forall a b f. Traversable f => (a -> Maybe b) -> f a -> Maybe (f b)

Map an array conditionally, only return the array when all elements were mapped. Note that this function is an alias for traverse. This is specific behavior for the implementation of <*> for Applicative Maybe.

Hint: mapAny can be found in Data.Foldable.Extra

mapAll (\x -> if x == 2 then Just 99 else Nothing) [1,2,3] == Nothing
mapAll (\x -> Just (x * 2)) [1,2,3] == Just [2,4,6]