Могу ли я иметь дело со многими файлами одновременно в Haskell? - PullRequest
1 голос
/ 25 сентября 2010

Мне нужно решить следующую проблему.

есть много файлов, скажем, 3, например, со следующим содержанием

file1

a1

a2

a3

a4

a5

a6

......

file2

b1

b2

b3

b4

b5

b6

......

file3

c1

c2

c3

c4

c5

c6

......

моя программа должна принимать имена файлов в параметре, читать эти файлыи выведите следующий результат

"a1 b1 c1"

"a2 b2 c2"

"a3 b3 c3"

"a4 b4 c4"

"a5 b5 c5"

"a6 b6 c6"

......

Я уже написал одну версию программы,но он начинается с чтения всех файлов, и это очень неэффективно, потому что этот файл может иметь размер 200 МБ.

как записатьПрограмма для извлечения строки в каждом файле и отображения моих совпадений перед переходом к следующим строкам в файлах.Это, безусловно, позволит избежать загрузки всех файлов и эффективно использовать сборщик мусора?

изображения профиля

извините, я не знаю, как вставить сюда изображения, это всегда дает сбой, но во время профилирования использование памяти выглядит как лестница сверху вниз

alt text

хорошо, это работает 1

спасибо за ответ

Ответ

Благодаря FUZxxi его ответ действительно помог мне, но была проблема, когда файлы не имели одинаковое количество строк, чтобы решить эту проблему, я переписал егозапрограммируйте таким образом

printLines :: [[String]] -> IO ()

printLines [] = return ()

printLines ss = do

    ss' <- printFirstLine ss

    if and $ map null ss' then putStrLn "finish" else printLines ss'





printFiles :: [FilePath] -> IO ()

printFiles paths = do

  files <- mapM readFile paths

  let fileLines = map lines files

  printLines fileLines



sliceFirstRow :: [[String]] -> ([String],[[String]])

sliceFirstRow list = unzip $ map getFirst list



printFirstLine :: [[String]] -> IO ([[String]])

printFirstLine ss = do

  let (fline,lline) = sliceFirstRow ss

  mapM_ putStrLn fline

  return lline    



getFirst :: [String] -> (String, [String])

getFirst [] = ("",[])

getFirst (x:xs) = (x,xs)

Еще раз спасибо

1 Ответ

2 голосов
/ 25 сентября 2010

Я бы сделал что-то вроде этого:

printFiles :: [FilePath] -> IO ()
printFiles paths= do
  files <- mapM readFile paths
  let fileLines = map lines files
  printLines fileLines
  where
  sliceFirstRow :: [[String]] -> ([String],[[String]])
  sliceFirstRow list = unzip $ map helper list where
    helper (x:xs) = (x,xs)
    helper []     = "" -- Your behaviour here
  printFirstLine :: [[String]] -> IO ([[String]])
  printFirstLine ss = do
    let (fline,lline) = sliceFirstRow ss
    mapM_ putStrLn fline
    return lline
  printLines :: [[String]] -> IO ()
  printLines [] = return ()
  printLines ss = do
    ss' <- printFirstLine ss
    printLines ss'

Хотя это и не проверено, оно должно быть хорошо для памяти.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...