我希望能够在一行上输入一个整数序列,例如:
97, 128, 125, 17, 2
并让Haskell程序将输入转换为整数列表,例如:
[97, 128, 135, 17, 2]
这样我就可以使用另一个整数列表对zipWith
(列表)列表进行一些数学运算。遇到麻烦。我尝试使用read
和words
函数,但我无法达到预期的结果。有什么想法吗?
答案 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]
由于我只是使用空格来分隔数字,所以我不必使用过滤器,但感谢发布它,因为现在我更好地理解了语法。
唐