0

Consider a string of a2b4g9.

How would I be able to transform it into a two-dimensional array of types [(char,int)] like

(a,2)
(b, 4)
(g, 9)

Would I use concat or something else?

How can this be done?

3
  • 3
    Can you please try to work a bit more on your questions? You've asked the same question over and over again; all your questions are basically just to solve parts of the other question. Commented Mar 6, 2011 at 20:29
  • And BTW, [(Char,Int)] isn't a two-dimensional array. It's more a list of tuples. Commented Mar 6, 2011 at 20:47
  • 2
    I highly recommend you read Learn You a Haskell. It provides great general insight on how to do things in Haskell. Commented Mar 6, 2011 at 20:53

2 Answers 2

5

I'd suggest that the easiest way is just to write a recursive function to do it. Something like this should work as long as your numbers never go higher than 9:

toTuple :: String -> [(Char,Int)]

toTuple [] = []
toTuple (letter:reps:rem) = (letter,read [reps]) : toTuple rem

If your numbers do go higher than 9 then it gets a bit more complicated, because the number of repetitions is variable length.

(EDIT: FUZxxl and I posted almost identical solutions around the same time, but that's because it's the obvious answer. I didn't see his post before posting myself)

Another solution is to write a function to take every 2nd element of a list, and then combine the resulting letters and repetitions lists using the zip function.

Or you could go a bit over the top and user a parser combinator like parsec:

import Text.Parsec
import Control.Monad

parseFunc :: String -> String -> Either ParseError [(Char,Int)]

parseFunc = parse (many letterPair)
    where 
        letterPair = do
            l <- letter
            d <- many digit
            return (l, read d)
Sign up to request clarification or add additional context in comments.

2 Comments

Why not applicative style? parseFunc = parse (many $ (,) <$> letter <*> (read <$> many digit)) ;)
I just thought that do notation would be easier to read for someone new to Haskell. Your example is definitely concise, but it's not that easy to read for someone new to the language. Originally I used liftM2, but I got rid of that too to make it easier to understand.
0

Try this one:

f :: String -> [(Char,Int)]
f [] = []
f (x:y:zs) = (x,read [y]) : f zs

Or this one:

import Data.List
import Data.Maybe
f :: String -> [(Char,Int)]
f = catMaybes . snd . mapAccumL a Nothing where
  a acc x = maybe (Just x,Nothing) (\acc' -> (Nothing,Just (acc',read [x]))) acc

3 Comments

read y doesn't work because read takes a string, not a Char. you need read [y]... see my answer below, which I posted independently (I didn't see FUZxxl's almost identical code)
Should be read [y], also might want to add an explicit type signature of f :: String -> [(Char, Int)]
@pelotom: My second function is what you suggested in the last sentence. It seems to be far more complicated. (Basically, I'm using a Maybe to get two consecutive elements here.)

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.