【问题标题】:count number of chars in String计算字符串中的字符数
【发布时间】:2018-04-20 03:15:06
【问题描述】:

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

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

这将返回 (char,1) 形式的元组。我也可以消除这个列表中的重复项,所以我现在没有做的是编写一个类似的函数

    fun count(s:string,l: (char,int) list) 

通过增加特定元组组件的字符串“迭代”。我怎样才能递归地做到这一点?对不起菜鸟问题,但我是函数式编程的新手,但我希望这个问题至少可以理解:)

【问题讨论】:

  • 您想测量单个字符、字符子集还是字符串中所有字符的出现频率?
  • 嗨。我想测量所有字符的频率。结果应该是一组元组(每个字符一个)

标签: string recursion count char sml


【解决方案1】:

我将问题分成两部分:增加单个字符的频率,遍历字符串中的字符并插入每个字符。增加频率取决于您之前是否已经看过该角色。

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

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

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2019-09-14
    • 2016-10-28
    • 2018-04-20
    • 1970-01-01
    • 2023-04-06
    • 1970-01-01
    相关资源
    最近更新 更多