计算String中的字符数

时间:2017-11-07 16:19:31

标签: string recursion count char sml

在SML中,如何使用递归计算字符串中字符的出现次数? 输出应采用(char,#AppearenceOfChar)的形式。 我设法做的是

    fun frequency(x) = if x = [] then [] else [(hd x,1)]@frequency(tl x)

将返回表格(char,1)的tupels。我也可以删除此列表中的重复项,因此我现在未能做的就是编写像

这样的函数
    fun count(s:string,l: (char,int) list) 

'迭代'通过增加特定tupel组件的字符串。我怎么能递归地做到这一点?抱歉没有问题,但我是函数式编程的新手,但我希望这个问题至少可以理解:)

1 个答案:

答案 0 :(得分:0)

我将问题分解为两个:增加单个字符的频率,迭代字符串中的字符并插入每个字符。增加频率取决于你之前是否已经看过这个角色。

fun increaseFrequency (c, []) = [(c, 1)]
  | increaseFrequency (c, ((c1, count)::freqs)) =
      if c = c1
      then (c1, count+1)
      else (c1,count)::increaseFrequency (c, freqs)

这提供了具有以下类型声明的函数:

val increaseFrequency = fn : ''a * (''a * int) list -> (''a * int) list

因此,给定一个字符和一个频率列表,它会返回一个更新的频率列表,其中字符已插入频率为1,或者其现有频率已增加1,方法是对每个元组执行线性搜索,直到要么找到正确的,要么满足列表的结尾。保留所有其他字符频率。

迭代字符串中字符的最简单方法是将explode转换为字符列表,并将每个字符插入以空列表开头的累积频率列表中:

fun frequencies s =
    let fun freq [] freqs = freqs
          | freq (c::cs) freqs = freq cs (increaseFrequency (c, freqs))
    in freq (explode s) [] end

但这不是一次迭代一个字符串的非常有效的方法。或者,您可以通过索引访问每个字符,而无需转换为列表:

fun foldrs f e s =
  let val len = size s
      fun loop i e' = if i = len
                      then e'
                      else loop (i+1) (f (String.sub (s, i), e'))
  in loop 0 e end

fun frequencies s = foldrs increaseFrequency [] s

您可能还会考虑使用比列表更有效的集合表示来减少线性时间插入。