如何将字符串转换为整数列表?

时间:2015-09-17 15:56:58

标签: parsing haskell

我希望能够在一行上输入一个整数序列,例如:

97, 128, 125, 17, 2

并让Haskell程序将输入转换为整数列表,例如:

[97, 128, 135, 17, 2]

这样我就可以使用另一个整数列表对zipWith(列表)列表进行一些数学运算。遇到麻烦。我尝试使用readwords函数,但我无法达到预期的结果。有什么想法吗?

4 个答案:

答案 0 :(得分:6)

一种可能的(同样,quick'n'dirty)解决方案是使用read和为列表定义的实例,它需要格式为[item1, item2, item3...]的字符串:

convert :: String -> [Int]
convert s = read $ "[" ++ s ++ "]"

更强大的解决方案是使用filter或类似解析(如另一个答案中所示)或使用解析库来正确完成工作。

答案 1 :(得分:5)

仅使用words的问题是仍会包含逗号(,)。

快速而肮脏的黑客可能首先将所有字符而不是数字映射到空格:

import Data.Char(isDigit)

cnv x | isDigit x = x
      | otherwise = ' '

然后使用:

map read . words . map cnv :: Read b => [Char] -> [b]

<强>演示

*Main> ((map read . words . map cnv) "97, 128, 125, 17, 2" :: [Int]
[97,128,125,17,2]

潜在的问题当然是你省略了[A-z]个字符等。此外,这种方法效率不高。

一个优点是,通过使用read,所有可以read的项目仍然可以处理“字词”流。

  

为什么不过滤?

     

显然,也可以使用过滤器来获得例如空格和数字。例如

map read . words . filter (\x -> isDigit x || isSpace x)
     

一个潜在的问题是数字可能没有空格(),而只能用逗号(,),分号(;),使用上面的表达式会生成正确的结果:

(map read . words . filter (\x -> isDigit x || isSpace x)) "97, 128, 125, 17, 2" :: [Int]
[97,128,125,17,2]
     

(map read . words . filter (\x -> isDigit x || isSpace x)) "97,128,125,17,2" :: [Int]
[97128125172]
     

答案 2 :(得分:2)

您指定的任务属于文本解析的范畴。面对这样的问题时,安全的选择是使用“parsec”或“attoparsec”库来接近它。这些库提供的API以安全且可组合(因此可扩展)的方式抽象解析。

以下是为任务编写“attoparsec”解析器的方法:

listOfInts :: Parser [Int]
listOfInts =
  sepBy decimal separator
  where
    separator =
      skipSpace *> char ',' *> skipSpace

请注意,提供的实现已经允许您解析一个格式不正确的输入,其中分隔符可能在逗号前后有多个空格或没有空格。还要注意使用这样的解析器表达这种已经很复杂的条件是多么简单。

答案 3 :(得分:0)

谢谢大家的帮助。对于我的应用程序,这似乎运作良好:

myInput <- getLine
  

123 23 345 23

(map read . words) myInput::[Int]

我理解为什么括号出现在他们所处的位置时有点麻烦,但这似乎也有效:

myInput <- getLine

234 34 235 465 34

map read $ words myInput::[Int]

由于我只是使用空格来分隔数字,所以我不必使用过滤器,但感谢发布它,因为现在我更好地理解了语法。