Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Taking sub-arrays in Haskell

Tags:

haskell

How do I get a sub array in Haskell?

like image 862
Rnet Avatar asked Apr 02 '11 08:04

Rnet


3 Answers

I think you're looking for is the 'Derived arrays' section in the Data.Array documentation: http://hackage.haskell.org/packages/archive/array/latest/doc/html/Data-Array.html#5 which houses the function:

ixmap :: (Ix i, Ix j) => (i, i) -> (i -> j) -> Array j e -> Array i e

ixmap allows for transformations on array indices. It may be thought of as providing function composition on the right with the mapping that the original array embodies.

A similar transformation of array values may be achieved using fmap from the Array instance > of the Functor class.

The following code:

ixmap newBounds trans backingArray

would return an array with bounds newBounds, and when indexed with !i, the index transformation function is applied onto the index i before being used to index backingArray.


Example if you had the array "Hello World" (helloWorldArray below) and you want to only see "ell" as a derived zero-based (sub-)array:

> let helloWorldArray = listArray (0,length str - 1) str    -- 0-based array
     where str = "Hello World"

> let ellArray = ixmap (0,2) succ helloWorldArray           -- also 0-based array

> ellArray ! 0
'e'
> ellArray ! 1
'l'
> ellArray ! 2
'l'

Here we say that our new array ellArray has indices from 0 through 2. Our index transformation is simply to add one (succ), because we want to map the index range [0..2] to [1..3] in the original helloWorldArray.

Of course, ixmap is abstract enough to capture any index transformations: even as to view 2 dimensional arrays as 1 dimensional arrays and vice-versa. It's better to think of it as creating a 'view' onto array data rather than a 'sub-array' function.

For more examples you can look here: http://zvon.org/other/haskell/Outputarray/ixmap_f.html

like image 165
fatuhoku Avatar answered Nov 16 '22 02:11

fatuhoku


Taking sub-arrays using the vector package is probably the easiest approach (assuming your question isn't actually asking about taking sub-lists).

The relevant functions from the general vector/array interface is:

  • slice :: Vector v a => Int -> Int -> v a -> v a

but you should also know about take and drop. slice takes a index and length, and extracts the sub-array.

like image 31
Don Stewart Avatar answered Nov 16 '22 02:11

Don Stewart


I didn't find any direct way to get a sub-array (i.e. slice), but here's one way to do it via an intermediate list.

import Data.Array

subArray :: Int -> Int -> Array -> Array
subArray i j a = listArray (0,j-i) $ map (a!) [i..j]
like image 2
shang Avatar answered Nov 16 '22 02:11

shang