1

In my program, I generate a list of numbers:

data = [2,3,2,5,2,7,2,3,2,11 ... ]

Now I want to write this list of numbers as a single-line comma-separated string in a file. I know I can use writeFile combined with Show:

writeFile "data.txt" $ show $ data

However, this will also print the square brackets at the beginning and end. Now I could remove the first and last characters from the string Show data by using reverse, but this is inefficient. At some point, the program is already traversing the list in order to write the characters to the file, so how can I make sure it doesn't write the first and last characters without doing an unnecessary traversal?

Will this do the job most efficiently?

writeFile "data.txt" $ drop 1 $ takeWhile (\c -> c/= ']') $ show data
Myridium
  • 789
  • 10
  • 20

2 Answers2

3

What you have is fine, but I think a neater way is not to use show on the list, but to show each element and put in the commas yourself, like this:

writeFile "data.txt" . intercalate "," . map show $ [1, 2, 3]

intercalate is from Data.List.

(by the way: you can't call a variable data, because that's a keyword)

David Fletcher
  • 2,590
  • 1
  • 12
  • 14
3

You have lot of way for doing this! Your data are converted to strings, and, you can now use them:

In your case, you can write your code like this (each element of the list is read one time and directly converted)

writeFile "data.txt" $ Data.List.foldl (\x y -> x ++ show y ++ ",") "" data

and without last comma:

writeFile "data.txt" $ Data.List.tail $ Data.List.foldl (\x y -> x ++ "," ++ show y) "" data

or using intercalate from Data.List

 Data.List.intercalate "," $ Data.List.map (\x -> show x) data

Similar questions are on stackoverflow:

Community
  • 1
  • 1
Mathieu Kerjouan
  • 495
  • 5
  • 13
  • 1
    Nice. Note that the fold approach will generate a trailing comma, while intercalate does not. – chi Sep 22 '16 at 09:02
  • Yep, sorry, Solution here: `Data.List.tail $ Data.List.foldl (\x y -> x ++ "," ++ show y) "" data`. – Mathieu Kerjouan Sep 22 '16 at 09:15
  • 2
    `foldl` is a bad choice here. Try it in ghci on `[1..1000000]` and watch it crawl. You're forcing `(++)` to associate to the left and that makes it do quadratic work repeatedly traversing `"1"` then `"1,2"` then `"1,2,3"` etc. Use `foldr`. – David Fletcher Sep 22 '16 at 10:12
  • and if I do something like that? `Data.List.foldr (\x y -> "," ++ show x ++ y ) "" data` – Mathieu Kerjouan Sep 22 '16 at 10:23