我如何解析Haskell中的整数矩阵? [英] How do I parse a matrix of integers in Haskell?

查看:126
本文介绍了我如何解析Haskell中的整数矩阵?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

所以我读过这个理论,现在试图解析Haskell中的一个文件 - 但是没有到任何地方。这太奇怪了......



以下是输入文件的外观:

  mn 
k1,k2 ...

a11,....,an
a21,.... a22
...
am1 ... amn

其中m,n只是整数, K = [k1,k2 ...] 是一个整数列表, a11..amn 是一个矩阵(a列表): A = [[a11,... a1n],... [am1 ... amn]]



以下是我的快速Python版本:
$ b

  def parse(filename): 

形式输入:
mn
k1,k2 ...

a11,...,an
a21,... a22
...
am1 ... amn



f =打开(文件名)
(m,n)= f.readline()。split()
m = int(m)
n = int(n)

K = [int(k)for k in f.readline()。split()]

#Matri x - 列表列表
A = []
在范围内(m):
row = [float(el)for f.readline()。split()]
A.append(row)

return(m,n,K,A)

以下是我在Haskell中得到的(不是很强):

  import System.Environment 
import Data.List

main = do
(fname:_)< - getArgs
putStrLn fname - 由于putStrLn进入IO()monad,我们不能只应用它
解析< - 解析fname
putStrLn解析

解析fname =执行
内容< - readFile fname
- ,,,缺少东西......我怎么能得到第一个元素,并在其上匹配?

返回内容

我对单子(以及上下文陷入我的陷阱!)和do语句。我真的想写这样的东西,但我知道这是错的:

  firstLine<  -  contents.head 
(m,n)< - map read(words firstLine)

因为内容不是列表 - 但是一个monad。



next 步骤的任何帮助都会很棒。

所以我刚发现了 你可以这样做:

  liftM行。 readFile 

获取文件中的行列表。然而,这个例子仍然只是转换了ENTIRE文件,并没有使用第一行或第二行......

解决方案

非常简单的版本可能是:

$ p $ import Control.Monad(liftM)

- - 这纯粹运行在字符串
列表上,并且当传递的东西不是
时 - 匹配模式
parse_lines :: [String] - > (Int,Int,[Int],[[Int]])
parse_lines(mn_line:ks_line:matrix_lines)=(m,n,ks,matrix)
其中[m,n] = read_ints mn_line
ks = read_ints ks_line
matrix = parse_matrix matrix_lines

- 这里是循环剩余行以形成矩阵
parse_matrix :: [String] - > ; [[Int]]
parse_matrix lines = parse_matrix'lines []
其中parse_matrix'[] acc =反向acc
parse_matrix'(l:ls)acc = parse_matrix'ls $(read_ints l ):acc

- 这里给出读取
的正确签名read_ints :: String - > [Int]
read_ints =地图读取。单词

- 读取文件内容并将结果提取到IO
parse_file :: FilePath - > IO(Int,Int,[Int],[[Int]])
parse_file filename = do
file_lines< - (liftM lines。readFile)filename
return $ parse_lines file_lines

您可能希望查看Parsec进行更好的解析,并提供更好的错误处理功能。

  * Main Control.Monad> parse_filetest.txt
(3,3,[1,2,3],[[1,2,3],[4,5,6],[7,8,9]])


So I've read the theory, now trying to parse a file in Haskell - but am not getting anywhere. This is just so weird...

Here is how my input file looks:

        m n
        k1, k2...

        a11, ...., an
        a21,....   a22
        ...
        am1...     amn

Where m,n are just intergers, K = [k1, k2...] is a list of integers, and a11..amn is a "matrix" (a list of lists): A=[[a11,...a1n], ... [am1... amn]]

Here is my quick python version:

def parse(filename):
    """
    Input of the form:
        m n
        k1, k2...

        a11, ...., an
        a21,....   a22
        ...
        am1...     amn

    """

    f = open(filename)
    (m,n) = f.readline().split()
    m = int(m)
    n = int(n)

    K = [int(k) for k in f.readline().split()]

    # Matrix - list of lists
    A = []
    for i in range(m):
        row = [float(el) for el in f.readline().split()]
        A.append(row)

    return (m, n, K, A)

And here is how (not very) far I got in Haskell:

import System.Environment
import Data.List

main = do
    (fname:_) <- getArgs
    putStrLn fname --since putStrLn goes to IO ()monad we can't just apply it
    parsed <- parse fname
    putStrLn parsed

parse fname = do
    contents <- readFile fname
    -- ,,,missing stuff... ??? how can I get first "element" and match on it?

    return contents

I am getting confused by monads (and the context that the trap me into!), and the do statement. I really want to write something like this, but I know it's wrong:

firstLine <- contents.head
(m,n) <- map read (words firstLine)

because contents is not a list - but a monad.

Any help on the next step would be great.

So I've just discovered that you can do:

 liftM lines . readFile

to get a list of lines from a file. However, still the example only only transforms the ENTIRE file, and doesn't use just the first, or the second lines...

解决方案

The very simple version could be:

import Control.Monad (liftM)

-- this operates purely on list of strings
-- and also will fail horribly when passed something that doesn't 
-- match the pattern
parse_lines :: [String] -> (Int, Int, [Int], [[Int]])
parse_lines (mn_line : ks_line : matrix_lines) = (m, n, ks, matrix)
    where [m, n] = read_ints    mn_line
          ks     = read_ints    ks_line
          matrix = parse_matrix matrix_lines

-- this here is to loop through remaining lines to form a matrix
parse_matrix :: [String] -> [[Int]]
parse_matrix lines = parse_matrix' lines []
    where parse_matrix' []       acc = reverse acc
          parse_matrix' (l : ls) acc = parse_matrix' ls $ (read_ints l) : acc

-- this here is to give proper signature for read
read_ints :: String -> [Int]
read_ints = map read . words

-- this reads the file contents and lifts the result into IO
parse_file :: FilePath -> IO (Int, Int, [Int], [[Int]])
parse_file filename = do
    file_lines <- (liftM lines . readFile) filename
    return $ parse_lines file_lines

You might want to look into Parsec for fancier parsing, with better error handling.

*Main Control.Monad> parse_file "test.txt"
(3,3,[1,2,3],[[1,2,3],[4,5,6],[7,8,9]])

这篇关于我如何解析Haskell中的整数矩阵?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆