Ocaml 如何计算字符列表中重复出现的字符数?

Ocaml 如何计算字符列表中重复出现的字符数?,ocaml,Ocaml,我的目标是获取一个字符列表,如: 计算重复字符的数量,并将其转换为(int*char)列表,如下所示: [(5,'a');(3,'b');(1,'a');(4,'d')] 我完全迷路了,对OCaml也是非常陌生的。以下是我得到的代码: let to_run_length(lst:char list):(int*char)list= 匹配lst与 | [] -> [] |h::t-> 让计数=整数0英寸 而t[]做什么 如果h=t,则 计数:=计数+1; 完成; 我正在努力研究如何像检查C

我的目标是获取一个字符列表,如:


计算重复字符的数量,并将其转换为(int*char)列表,如下所示:

[(5,'a');(3,'b');(1,'a');(4,'d')]
我完全迷路了,对OCaml也是非常陌生的。以下是我得到的代码:

let to_run_length(lst:char list):(int*char)list=
匹配lst与
| [] -> []
|h::t->
让计数=整数0英寸
而t[]做什么
如果h=t,则
计数:=计数+1;
完成;
我正在努力研究如何像检查C或Python中的数组一样检查列表。我不允许使用折叠功能或地图或类似的东西

编辑:更新代码,在
列表上产生异常。第n个

let rec to_run_length (lst : char list) : (int * char) list =
  let n = ref 0 in
  match lst with
  | [] -> []
  | h :: t -> 
    if h = List.nth t 0 then n := !n + 1 ;
              (!n, h) :: to_run_length t ;;
编辑:添加了嵌套匹配,导致函数无法工作。。。但是没有错误

let rec to_run_length (lst : char list) : (int * char) list =
  match lst with
  | [] -> []
  | h :: t -> 
    match to_run_length t with
    | [] -> []
    | (n, c) :: tail -> 
      if h <> c then to_run_length t
      else (n + 1, c) :: tail ;;

回答您的问题的一种方法是指出OCaml中的列表与C或Python中的数组不同。没有(固定时间)的方法可以像索引数组那样索引OCaml列表

如果您想以命令式风格编码,可以将OCaml列表视为C语言中的列表,即可以从一个方向从头到尾遍历的链接结构

要实现这一点,您确实需要一个
while
语句,只要列表不为空,该语句就会继续。在每个步骤中,您都会检查列表的标题,并相应地更新输出。然后用列表的尾部替换列表

为此,您需要使用引用来保存输入和输出。(作为旁注,这里有
int 0
您几乎肯定想要
ref 0
。也就是说,您想要使用一个引用。没有名为
int
的预定义OCaml函数或操作符)

然而,学习OCaml的通常原因是学习功能性风格。在这种情况下,您应该考虑使用递归函数来计算所需的值

为此,您需要一个基本情况和一种将非基本情况简化为可以递归求解的较小情况的方法。一个很好的基本情况是空列表。该输入的期望输出(大概)也是一个空列表

现在假设(通过递归假设)您有一个可以工作的函数,并且您得到一个非空列表。您可以在列表的尾部调用函数,它(根据假设)为您提供了尾部的运行长度编码版本。您需要对此结果执行什么操作才能在前面再添加一个字符?这就是你必须弄明白的

更新

正如您所说,您的代码越来越近了

您需要问问自己如何在编码值的开头添加新字符。在您的代码中有以下内容,例如:

. . .
match to_run_length t with
| [] -> []
. . .
这表示如果尾部为空,则返回空编码。但这没有道理。您知道输入中有一个字符(即,
h
)。您应该返回某种类型的结果,包括
h


通常,如果返回的列表以
h
开头,则希望在第一组的计数中添加1。否则,您需要将新组添加到返回列表的前面。

谢谢您的输入!我一直在努力开发一个递归函数来解决这个问题。我已经用新代码更新了我的问题。我得到了一个例外:失败“n”这有一些正确的想法,但并不能让你一路走下去。首先,在处理递归调用返回时涉及到一些情况。首先,它可能不会以与
h
(列表的开头)相同的字符开头。其次,它实际上可能以与
h
相同的字符开头。第三种情况(如果与第一种情况不同)可能是空的。您可能应该考虑将返回值与一些模式进行匹配,以区分这些情况。作为另一个注释,不要使用
List.nth
。正如我所说,列表不能在固定时间内编制索引。所以你不应该把它们看作数组。您不需要为任何列表编制索引来编写好的解决方案。那么嵌套的匹配循环在这里有用吗?我的另一个想法是这样做:
h::t->match to_run_length with
然后看看你提到的3个案例。再次感谢你的帮助!请不要以使现有答案无效的方式更改您的问题。我已经将您的问题更改为加法,而不是更改现有代码,尽管从技术上讲,当您遇到完全不同的问题时,您应该问一个单独的问题。对此我深表歉意!我是堆栈溢出社区的新手。
. . .
match to_run_length t with
| [] -> []
. . .