每个`String`的第一个`Char`分区`[String]`

时间:2017-07-29 05:56:17

标签: string haskell partitioning

我正在尝试编写具有以下类型的函数:

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可以是NothingJust s。如果是Nothing,我想insert x [xs] partitioned。如果是Just s,那么我想要insert x (xs:s) partitioned

我很难弄清楚如何检查suffixes是什么。我认为我需要???的某种模式匹配,但无法弄明白。

2 个答案:

答案 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可以是NothingJust 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