sanic
sanic

Reputation: 2085

Haskell: Output list of tuples as string output

I'm trying to get this list of tuples:

[(2,"a"), (1,"a"), (1,"b"), (1,"c"), (2,"dd")]

into this string output

a 1,2

b 1

c 1

dd 2

I assume I need to use the unzip and unlines functions. But I also saw some solutions using the show function which makes the integers strings. Any ideas?

Upvotes: 0

Views: 2779

Answers (3)

Landei
Landei

Reputation: 54584

Work step by step. You could start with the groupBy function:

groupBy (\x y-> (snd x)==(snd y)) [(2,"a"), (1,"a"), (1,"b"), (1,"c"), (2,"dd")]

gives you

[[(2,"a"),(1,"a")],[(1,"b")],[(1,"c")],[(2,"dd")]]

The next step would be "totalling" the inner lists, map and foldL (and depending on your requirements maybe sortBy) should be helpful. If you have this, constructing the output is trivial (using show, as you already mentioned).

Upvotes: 0

bheklilr
bheklilr

Reputation: 54058

Break the problem down into steps. What you really want to do first is aggregate all the tuples that have the same string in the second position, so you'll have a function like

aggregate :: [(Int, String)] -> [([Int], String)]

So for your input list you would get the output

[([1, 2], "a"), ([1], "b"), ([1], "c"), ([2], "dd")]

Your hints are

aggregate items = someFunc (map (\(num, str) -> ([num], str)) items)

And take a look at foldr. Before you ask a follow up question about foldr, there are probably hundreds of stackoverflow answers showing how to use it already, take some time to figure it out or it'll get closed immediately as a duplicate.

Then you need a function to convert a single tuple of this form into a single String for outputting:

prettyPrint :: ([Int], String) -> String
prettyPrint (nums, str) = str ++ " " ++ joinWithComma (map show nums)

Where you'll have to implement joinWithComma yourself. Then you need to calculate this and print it for each item in your aggregated list, mapM_ and putStrLn would be preferred, so your main might look like

main :: IO ()
main = do
    let inputList = [(2,"a"), (1,"a"), (1,"b"), (1,"c"), (2,"dd")]
    mapM_ (putStrLn . prettyPrint) (aggregate inputList)

Upvotes: 2

ErikR
ErikR

Reputation: 52039

If you have this list:

pairs = [ ("a", [1,2]), ("b", [1]), ("c", [1]), ("dd", [2]) ]

then you can get the desired output with:

putStrLn $ unlines [ x ++ " " ++ unwords (map show ys) | (x, ys) <- pairs ]

but you have to figure out how to get the pairs list first.

Upvotes: 2

Related Questions