我正在尝试编写具有以下类型的函数:
partitionByFirstChar :: [String] -> Map.Map Char [String]
partitionByFirstChar xs
将返回Map
,其键是列表xs
中每个字符串的第一个字符,其值是后缀列表(即除第一个字符外的所有字符)那些字符串。
我尝试这样做的方法如下:
partitionByFirstChar [] = Map.empty
partitionByFirstChar ((x:xs):xss)
= ???
where partitioned = partitionByFirstChar xss
suffixes = partitioned !? x
现在suffixes
可以是Nothing
或Just s
。如果是Nothing
,我想insert x [xs] partitioned
。如果是Just s
,那么我想要insert x (xs:s) partitioned
。
我很难弄清楚如何检查suffixes
是什么。我认为我需要???
的某种模式匹配,但无法弄明白。
答案 0 :(得分:0)
如果您愿意使用multimap
套餐,它很容易解决这个问题。
λ> import qualified Data.MultiMap as MM
λ> MM.toMap . MM.fromList . fmap (\(x:xs) -> (x, xs)) $ ["apple", "avocado", "bagel"]
fromList [('a',["pple","vocado"]),('b',["agel"])]
正如@ Alec的评论指出的那样, fromListWith
可能是一个更好的选择,如果你不需要使用MultiMap
类型。虽然性能可能不是很好,但由于列表连接。
λ> import qualified Data.Map as M
λ> M.fromListWith (<>) . fmap (\(x:xs) -> (x, [xs])) $ ["apple", "avocado", "bagel"]
fromList [('a',["vocado","pple"]),('b',["agel"])]
答案 1 :(得分:0)
现在
suffixes
可以是Nothing
或Just s
。如果是Nothing
,我想insert x [xs] partitioned
。如果是Just s
,那么我想要insert x (xs:s) partitioned
。
这里的基本方法是使用case of
:
partitionByFirstChar [] = Map.empty
partitionByFirstChar ((x:xs):xss) = let
partitioned = partitionByFirstChar xss
suffixes = partitioned !? x
in case suffixes of
Nothing -> insert x [xs] partitioned
Just s -> insert x (xs:s) partitioned
上面的代码仍缺少空字符串的分支,例如:
partitionByFirstChar ("":xss) = partitionByFirstChar xss