我使用一些函数和列表理解生成了一个元组列表,像这样
[(x,y, func (x,y)) | x<-[xmin,(xmin+dx)..xmax], y<-[ymin,(ymin+dy)..ymax]]
因此,我几乎创建了许多点的3D坐标列表。
现在我的问题是,如何有效地将此列表写入文件中?我需要像这样
x0 y0 z0
x1 y1 z1
x2 y2 z2
....
要写入文件,您可以执行以下操作:
main = do
h <- openFile "output.txt" WriteMode
hPutStrLn h "Hello, file system"
hClose h
一种更安全的方法是使用writeFile :: FilePath -> String -> IO ()
,如果发生错误,它将关闭句柄,但是您必须首先生成整个内容:
main = let contents = "Hello, " ++ "file" ++ " system"
in writeFile "output.txt" contents
我会让您决定要使用哪个。writeFile
由于其安全性,我会推荐该方法。
接下来,我来看一下Data.List.intercalate
。如果您使用的是命令式语言(例如Python),则可能熟悉stringjoin
方法。在Python中:
with open('output.txt', 'w') as f:
f.write(' '.join(['Hello,', 'file', 'system']))
这会将字符串写入Hello, file system
文件output.txt
。该intercalate
功能是在Haskell非常相似:
main = writeFile "output.txt" $ intercalate " " ["Hello,", "file", "system"]
-- This is the string to join by ----^ ^
-- These are the strings being joined together ------|
现在,您所需要做的就是弄清楚如何将数据转换为字符串以将其写到文件中。我建议写一个函数
showTriple :: Show a => String -> (a, a, a) -> String
showTriple sep (x, y, z) = ???
这将三元组转换为sep
定界字符串。这样,您可以轻松地将该空间换成制表符,逗号或任何其他可能要使用的符号。
如果您遇到困难,只需使用进度更新来编辑问题,并显示代码和注释,告诉我是什么让您陷入困境。
现在您已经自己解决了问题,下面是使用这些功能的解决方法:
-- This is just your list of data from above
range :: ((Double, Double) -> Double) -> (Double, Double, Double) -> (Double, Double, Double) -> [(Double, Double, Double)]
range func xs ys = [(x, y, func (x, y)) | x <- interval xs, y <- interval ys]
where
interval (tmin, tmax, dt)
| tmin < tmax = [tmin, tmin+dt .. tmax]
| otherwise = interval (tmax, tmin, dt)
writeDelimitedFile :: FilePath -> String -> [(Double, Double, Double)] -> IO ()
writeDelimitedFile file sep values = writeFile file $ delimitedString sep values
delimitedString :: String -> [(Double, Double, Double)] -> String
delimitedString sep values = intercalate "\n" $ map (showTriple sep) values
showTriple :: Show a => String -> (a, a, a) -> String
showTriple sep (x, y, z) = intercalate sep $ map show [x, y, z]
main :: IO ()
main = writeDelimitedFile "output.txt" " " $ range (uncurry (+)) (0, 10, 0.1) (0, 5, 0.1)
当然,您可以将其缩短很多,而无需定义单独的函数来完成所有工作并使用unwords
和unlines
代替intercalate
:
main :: IO ()
main = writeFile "output.txt" $ unlines
[unwords $ map show [x, y, z] |
(x, y, z) <- range (uncurry (+)) (0, 10, 0.1) (0, 5, 0.1)]
但这使以后更改变得更加困难。正如您所看到的,如果我们要防止它从屏幕的一侧移开,则无论如何都必须将其分成多行。
本文收集自互联网,转载请注明来源。
如有侵权,请联系 [email protected] 删除。
我来说两句