Форум программистов, компьютерный форум, киберфорум
Наши страницы
Haskell
Войти
Регистрация
Восстановить пароль
 
Рейтинг 4.50/6: Рейтинг темы: голосов - 6, средняя оценка - 4.50
aaleksander
111 / 85 / 21
Регистрация: 06.06.2011
Сообщений: 398
Записей в блоге: 1
1

Покритикуйте код: чтение файла и вывод данных в несколько колонок

14.03.2012, 13:59. Просмотров 1140. Ответов 3
Метки нет (Все метки)

Кто готов наставить новичка на путь истинный, любит Хаскель и кому нечем заняться, велком :-)
Скрипт читает файл вида:
101619|"Дмитрий"|"Владимирович"|"Абаренов"|78326||"N"||77713|9370|"N"
219670|"Камилбег"|"Магамедович"|"Абдулаев"|67|09.09.84|"N"||4265|2500|"N"
137385|"Магомед"|"Абдулаевич"|"Абдулаев"|20566|27.01.83|"N"||4267|9525|"N"
9556|"Александр"|"Леонидович"|"Абросимов"|4362|25.07.74|"N"||9119|7953|"N"
77150|"Роман"|"Николаевич"|"Авдеев"|229755|30.01.86|"N"||4261|3576|"N"
8041|"Владимир"|"Георгиевич"|"Аверин"|75|14.08.54|"N"||5241|3222|"N"
87874|"Евгений"|"Георгиевич"|"Аверин"|75|04.08.56|"N"||4261|2670|"N"
Каждую строку преобразует в список подстрок (разделяя через "|")
Удаляет двойные кавычки спереди и сзади, если есть.
И выводит это все на экран, разделяя колонки знаком табуляции.
Критика, оптимизации, фокусы и прочее - приветствуются.
Haskell
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
--разбивает строку с разделителем '|' на список строк
parse::String -> [String]
parse x
  | x <= "" = [] --если пустая строка, то пустой списко
  | snd (br x) <= "" = [x] -- если в строке только один элемент
  | otherwise = [fst (br x)] ++ parse (tail ( snd (br x)))  --берем первый элемент, вернутый breakом 
                                                            --и стыкуем сзади рекурсивный вызов остатка
                                                            --tail нужен, чтобы убрать "|" вначале
  where br ss = break ('|'==) ss
 
--убирает вначале и с конца двойную кавычку
strip::String -> String
strip "" = ""
strip (xs)
  | head xs <= '"' = strip $ tail xs
  | last xs <= '"' = init xs
  | otherwise = xs  
 
--склеить список строк в строку через сепаратор
join:: [String] -> String -> String
join [] sep = ""
join list sep = (strip (head list)) ++ sep ++ (join (tail list) sep) --попутно убираем кавычки
  
--печатаем список в одну строку через табуляцию
printListLn:: [String] -> IO()
printListLn list = do
  --склеим список в одну строку
  putStrLn $ join list "\t"
 
--печатать список списков строк
printDict:: [[String]] -> IO()
printDict [] = putStr ""
printDict list = do  
  printListLn $ head list  
  printDict $ tail list
 
main = do
  asppi <- readFile "asppi.txt"
  asppi_dict <- return $ map (parse) $ lines asppi  
  printDict asppi_dict
  putStrLn $ "Итого записей: " ++ (show $ length asppi_dict)
Спасибо.
0
Similar
Эксперт
41792 / 34177 / 6122
Регистрация: 12.04.2006
Сообщений: 57,940
14.03.2012, 13:59
Ответы с готовыми решениями:

Ввод/вывод. Покритикуйте код
Как можно это написать еще лучше (производительнее, эстетичнее, логичнее, экономнее по памяти и...

Вывод отчета в несколько колонок
Подскажите, пожалуйста, как можно вывести результат одного запроса в отчет в несколько колонок. Для...

Чтение и вывод данных из XML файла
Здрасте,проблема в следующем : имеется XML документ,выглядит вот так(маленький фрагмент) &lt;Da...

Вывод контента на главной в несколько колонок
Добрый день ! Нужно вывести контент на главной в 2 а лучше в 3 колонки как бы это сделать ? В инете...

Вывод текста в несколько колонок (Delphi 7)
Доброго времени суток! Подскажите какой-нибудь компонент для вывода текста в несколько колонок....

3
Nameless One
Эксперт С++
5790 / 3439 / 356
Регистрация: 08.02.2010
Сообщений: 7,448
14.03.2012, 17:15 2
Для разбора текста можно воспользоваться парсерными комбинаторами:

Haskell
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
import Text.ParserCombinators.Parsec
import System.IO
import System.Exit
import System.Environment
import Control.Applicative ((<*))
 
cell :: Parser String
cell = between (char '"') (char '"') cellItem
       <|> cellItem
       <?> "(Probably quoted) sequence of characters"
    where cellItem = many $ noneOf "\"|"
 
row :: Parser [String]
row = cell `sepBy1` char '|' <?> "cells separated by '|'"
 
table :: Parser [[String]]
table = row `sepEndBy1` newline <* eof <?> "rows separated by newline character"
 
run :: FilePath -> IO ()
run fname = do result <- parseFromFile table fname
               case result of
                 Right output -> display output
                 Left err     -> hPrint stderr err >> exitFailure
 
join :: String -> [String] -> String
join sep = foldl1 (\acc s -> acc ++ sep ++ s)
 
display :: [[String]] -> IO ()
display = putStr . join "\n" . map (join "\t")
                                       
main :: IO ()
main = do args <- getArgs
          case args of
            []      -> hPutStrLn stderr "Usage: parse FILE" >> exitFailure
            [fname] -> run fname
1
aaleksander
111 / 85 / 21
Регистрация: 06.06.2011
Сообщений: 398
Записей в блоге: 1
14.03.2012, 17:21  [ТС] 3
Цитата Сообщение от Nameless One Посмотреть сообщение
Для разбора текста существует можно воспользоваться парсерными комбинаторами:
О_о
Где тут смайлик "застрелиться"?

Добавлено через 1 минуту
Нашел. Парсерные комбинаторы во второй части "Мягкое введение в Хаскель". Ok
0
Nameless One
Эксперт С++
5790 / 3439 / 356
Регистрация: 08.02.2010
Сообщений: 7,448
14.03.2012, 17:32 4
Цитата Сообщение от aaleksander Посмотреть сообщение
Где тут смайлик "застрелиться"?
На самом деле, если ты знаешь базовые принципы комбинаторных парсеров, мой код понимается гораздо легче, чем твой

В книге Programming in Haskell (Graham Hutton) рассматривается реализация собственной парсерной библиотеки (и это действительно просто). Советую почитать, сразу все станет ясно.

join в моем коде следует заменить на стандартную функцию intercalate (из Data.List).

новая версия
Haskell
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
import Text.ParserCombinators.Parsec
import System.IO
import System.Exit
import System.Environment
import Control.Applicative ((<*))
import Data.List
 
cell :: Parser String
cell = between (char '"') (char '"') cellItem
       <|> cellItem
       <?> "(Probably quoted) sequence of characters"
    where cellItem = many $ noneOf "\"|"
 
row :: Parser [String]
row = cell `sepBy1` char '|' <?> "cells separated by '|'"
 
table :: Parser [[String]]
table = row `sepEndBy1` newline <* eof <?> "rows separated by newline character"
 
run :: FilePath -> IO ()
run fname = do result <- parseFromFile table fname
               case result of
                 Right output -> display output
                 Left err     -> hPrint stderr err >> exitFailure
 
display :: [[String]] -> IO ()
display = putStr . intercalate "\n" . map (intercalate "\t")
                                       
main :: IO ()
main = do args <- getArgs
          case args of
            []      -> hPutStrLn stderr "Usage: parse FILE" >> exitFailure
            [fname] -> run fname
2
MoreAnswers
Эксперт
37091 / 29110 / 5898
Регистрация: 17.06.2006
Сообщений: 43,301
14.03.2012, 17:32

Вывод контента в несколько колонок.не работает
Не могу понять что не правильно...Подскажите пожалуйста кто знает, буду очень признателен. ...

Сравнение несколько колонок одновременно и вывод результата
У меня есть несколько колонок 1) Данные для сравнения UPRN Floor Code Room 12555 1 HA...

Чтение и вывод данных с файла (решение квадратного уравнения)
уважаемые программисты помогите найти ошибку... прога должна считывать данные из файла... ...


Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
4
Ответ Создать тему
Опции темы

КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin® Version 3.8.9
Copyright ©2000 - 2019, vBulletin Solutions, Inc.
Рейтинг@Mail.ru