String 文本拆分器背后的Haskell模式匹配概念
我想知道这个代码片段背后的模式匹配概念:String 文本拆分器背后的Haskell模式匹配概念,string,haskell,pattern-matching,string-split,String,Haskell,Pattern Matching,String Split,我想知道这个代码片段背后的模式匹配概念: split :: String -> Char -> [String] split [] delim = [""] split (c:cs) delim | c == delim = "" : rest | otherwise = (c : head rest) : tail rest where rest = split cs delim 我知道head返回列表的第一个元素,tai
split :: String -> Char -> [String]
split [] delim = [""]
split (c:cs) delim
| c == delim = "" : rest
| otherwise = (c : head rest) : tail rest
where
rest = split cs delim
我知道
head
返回列表的第一个元素,tail
返回其余元素。但我仍然无法理解它的功能。这将获取一个字符串,并将其从给定字符分解为一个字符串列表。以下形式可能更清楚:
split [] delim = [""] -- a list containing only an empty String
split (c:cs) delim = let (firstWord:moreWords) = split cs delim
in if c == delim
then "" : firstWord : moreWords
else (c:firstWord) : moreWords
函数遍历输入字符串,将每个字符与分隔符进行比较。如果当前字符不是定界字符,则将其固定在拆分字符串剩余部分后产生的第一个单词(可能为空)的前面;如果当前字符是定界字符,则将向拆分剩余部分后的结果前面添加一个空字符串
例如,split“abc cde”的评估过程如下
split "abc cde" ' '
~> 'a' == ' ' ? No, next guard
~> ('a' : something) : somethingElse
其中,某物
和某物
稍后将通过拆分剩余的“bc cde”来确定。查看第一个字符后,确定无论最终结果是什么,它的第一个条目都以
'a'开头。接下来决定剩下的
split "bc cde" ' '
~> ('b' : something1) : somethingElse1
where (something1 : somethingElse1) = split "c cde" ' '
现在,结果第一个条目的前两个字符是已知的。然后从下一步开始,确定something1
以'c'
开头。最后我们得到了一个分隔符,在这种情况下,结果的第一个元素是在不参考后面的递归调用的情况下确定的,并且在递归中只剩下结果的其余部分
制定算法的另一种方法是(感谢@dave4420的建议)
因此,将空字符串添加到from将拆分字符串。我的意思是,字符串被分隔成一系列字符串的方式。?如果找到定界字符,它将返回什么。。。?如示例所示,一个名为“abc cde”的字符串需要与空格分隔。。然后,当它有一个“”时,它将返回“”、“cde”或“cde”。。head是否包含字符串列表?@Gihan拆分“abc cde”'
将生成[“abc”,“cde”]
。我不确定我是否理解你的下一个问题,但如果我理解:head
获取任何类型的列表,在split
中,它确实在String
列表中调用。是的。关于下一个问题,是这样的。我要拆分的字符串是“abc cde”
,因为它有7个字符,这有7个递归阶段。将从最后阶段开始。它将返回“E”
。第6次重复将返回E:F:Null
,如“EF”
中所示。第五个将返回D:E:F
,如中的“DEF”
所示。然后是第四层的空间。然后它将是:“DEF”
对的。这就是问题所在。它会以(“”,“DEF”)
或“DEF”
的形式从那里返回吗?如果它是(“”,“DEF”)
,那么在第三级,它本身将是C::“DEF”
返回“C”,“DEF”
对吗?我不知道。每个(有限且完全[spine]定义的)列表以空列表结尾[]
。每当到达分隔符(或输入的结尾)时,就会插入一个空列表(由Char
s组成,一个空字符串
)来标记一个块的结尾。
split input delim = foldr combine [""] input
where
combine c rest@(~(wd : wds))
| c == delim = "" : rest
| otherwise = (c : wd) : wds