我知道如何使用read
将String
更改为Int
,例如使用
map read ["3","2","1"] :: [[Int]]
但是当我遇到不规则的名单时,我就陷入困境,比如
["3","[3,5]","[5,3]"],["4","[1,9]","[2,3]"]
如何将其转换为[[3,[3,5],[5,3]],[4,[1,9],[2,3]]
?
答案 0 :(得分:3)
在Haskell中无法实现您的目标,因为值[[3, [3, 5], [5, 4]], [4, [1, 9], [2, 3]]
的类型无效。那里没有足够的近距离括号,你只有一个短。 [3, [3, 5]]
的类型是什么? [[Int]]
? [Int]
?两者都不合适。
即使你的例子也错了:
> map read ["3", "2", "1"] :: [[Int]]
[*** Exception: Prelude.read: no parse
因为[3, 2, 1]
的类型为[Int]
,而不是[[Int]]
。请记住,这不是Python,列表只能包含单一类型的元素。
相反,如果你有像["3", "[3,5]", "[5,3]"]
这样的输入,你可以用更像
import Text.Read (readMaybe)
readEither :: (Read a, Read b) => String -> Maybe (Either a b)
readEither s = case readMaybe s of
Just x -> Just $ Left x
Nothing -> case readMaybe s of
Just y -> Just $ Right y
Nothing -> Nothing
这可以表达得更短,但我认为这很好地说明了这一点。然后,您可以使用它来解析您的值:
parseMyList :: [String] -> [Maybe (Either Int [Int])]
parseMyList = map readEither
并将其用作
> parseMyList ["3", "[3,5]", "[5,3"] -- Incomplete last element!
[Just (Left 3), Just (Right [3,5]), Nothing]
我在那里留下了一个意外的错字,所以你可以看到它也没有优雅地失败。
可以使用Monoid
:
import Text.Read (readMaybe)
import Data.Monoid
readEither :: (Read a, Read b) => String -> Maybe (Either a b)
readEither = getFirst $ mconcat $ map First [fmap Left $ readMaybe s, fmap Right $ readMaybe s]
也许有人可以打高尔夫球。
答案 1 :(得分:0)
使用readMaybe作为bheklilr,我认为你可能会使用[[Int]]
作为结果数据类型。
> import Text.Read (readMaybe)
> map (\x->maybe [read x] id $ readMaybe x) ["3", "[3,5]", "[5,3]"] :: [[Int]]
[[3],[3,5],[5,3]]
如果你想要一个平面列表,你甚至可以在结果上使用concat
。