If statement OCaml-递归列表列表';if表达式';
我想创建一个rec函数,比如说If statement OCaml-递归列表列表';if表达式';,if-statement,recursion,ocaml,nested-lists,If Statement,Recursion,Ocaml,Nested Lists,我想创建一个rec函数,比如说oddlinenldbl,它将列表列表“L”作为参数,并返回一个“L”的副本,其中奇数长度的列表已“加倍”-加倍表示列表将与其自身连接 为了说明上述情况,我们的想法是: oddleninLdbl [[]; [5]; [23;5]; [45;65;2]; []; [34;85;7;22;1]];; 返回以下内容: [[]; [5;5]; [23;5]; [45;65;2;45;65;2]; []; [34;85;7;22;1;34;85;7;22;1]] 它还应适
oddlinenldbl
,它将列表列表“L”作为参数,并返回一个“L”的副本,其中奇数长度的列表已“加倍”-加倍表示列表将与其自身连接
为了说明上述情况,我们的想法是:
oddleninLdbl [[]; [5]; [23;5]; [45;65;2]; []; [34;85;7;22;1]];;
返回以下内容:
[[]; [5;5]; [23;5]; [45;65;2;45;65;2]; []; [34;85;7;22;1;34;85;7;22;1]]
它还应适用于任何列表类型,例如,这里的字符串:
oddleninLdbl [[]; ["mi";"lo"]; ["la"]; ["lo";"co";"mo"]]
应返回:
[[]; ["mi";"lo"]; ["la";"la"]; ["lo";"co";"mo";"lo";"co";"mo"]]
我一直在绕着这个绕圈子。如果我没有弄错的话,我知道我的“如果表达式”应该围绕列表中列表长度相关的内容旋转,当它是list.length mod 2=1
时,子列表应该与其自身连接
但是,我无法应用它,因为我从未使用过列表列表!这个函数应该如何编写?非常感谢你的帮助
编辑1:
我试着做了以下几件事
let double_list l = l@l;;
let rec oddleninLdbl l =
if l = []
then []
else (
let t = List.tl l in
if ((List.length l) mod 2 = 1)
then double_list l
else oddleninLdbl t
) ;;
但我得到的答案是:
# oddleninLdbl [[]; [5]; [23;5]; [45;65;2]; []; [34;85;7;22;1]] ;;
- : int list list =
[[5]; [23; 5]; [45; 65; 2]; []; [34; 85; 7; 22; 1]; [5]; [23; 5]; [45; 65; 2]; []; [34; 85; 7; 22; 1]]
# oddleninLdbl [[]; ["mi";"lo"]; ["la"]; ["lo";"co";"mo"]] ;;
- : string list list =
[["mi"; "lo"]; ["la"]; ["lo"; "co"; "mo"]; ["mi"; "lo"]; ["la"];["lo"; "co"; "mo"]]
# oddleninLdbl [5;6;3;4;6] ;;
- : int list = [5; 6; 3; 4; 6; 5; 6; 3; 4; 6]
# oddleninLdbl [4;5] ;;
- : int list = [5; 5]
# oddleninLdbl [4;5;8] ;;
- : int list = [4; 5; 8; 4; 5; 8]
# oddleninLdbl [4;5;8;9] ;;
- : int list = [5; 8; 9; 5; 8; 9]
# oddleninLdbl ["mi";"lo"] ;;
- : string list = ["lo"; "lo"]
# oddleninLdbl ["mi";"lo";"co"] ;;
- : string list = ["mi"; "lo"; "co"; "mi"; "lo"; "co"]
# oddleninLdbl ["mi"] ;;
- : string list = ["mi"; "mi"]
显然,这并不是我们所期望的功能。我的代码中的罪犯在哪里?有人能告诉我他们的诊断吗
编辑2:
let double_list l = (List.hd l)@(List.hd l);;
let p l = (List.length (List.hd l)) mod 2 = 1 ;;
let apply p double_list l =
let rec aux acc l = match l with
| [] -> List.rev acc
| hd :: tl ->
let hd = if p hd then double_list hd else hd in
aux (hd :: acc) tl ;;
我在这一个语法错误肯定我跳过了一些这里。你认为呢?在处理你不容易理解的结构时,一个很好的经验法则是分而治之 在这里,您的问题可以分解为多个部分:
让double_list l=(*将元素列表中的元素加倍*)
然后,您应该创建一个函数,该函数遍历元素列表,并在当前元素与谓词p
让应用p f l=
让rec aux acc l=将l与
|[]->List.rev acc
|hd::tl->
设hd=如果p hd那么f hd else hd in
辅助(hd::acc)tl
在辅助[]l中
现在,您只需要正确的谓词p
,您已经实现了函数f
,它应该可以完美地工作
总而言之,当你可以通过把问题划分成更小的问题来简化你的问题时,千万不要害怕表面上的复杂性
编辑:
这是您的代码:
let double_list l=l@l;;
让我来记录一下=
如果l=[]
然后[]
否则(
让t=List.tl输入
如果((列表长度l)模块2=1)
然后是双重列表
还有奥德列宁特吗
) ;;
这不是惯用的OCaml,请尝试改用模式匹配:
let double_list l=l@l;;
让我来记录一下=
匹配
| [] -> []
|hd::tl->
如果((列表长度l)模块2=1)
然后是双重列表
else-ldbl tl;;
如您所见,您正在检查
l
是否为奇数,而不是它的元素,这不是您想要做的。您需要检查hd
是否为奇数并将其加倍,然后继续遍历列表的其余部分,并将hd
(加倍或不加倍)附加到递归调用的结果中。在这里,当l
是奇数时,你将其加倍并停止,如果不是,你只需忘记列表的标题并加倍其余部分(因为其余部分在逻辑上是奇数列表)。我遵循了你的提示@Lhooq,在上面的编辑中将我的问题分解为多个部分。作为一名自学者,我正在努力理解这门语言,并希望获得一些关于我的错误的反馈。当然,射击,我会尝试回答;-)只要你们有时间,我已经在上面编辑了我的文章,通常它会出现在编辑1部分。我编辑了我的答案;-)我做了必要的修改,它成功了!在第一个函数中,我用它的hd替换了l。然后,在我的第二个函数的第二部分,用它的头替换了l。我还让它在末尾递归地遍历列表的其余部分,就像这样,对于第一种情况,double_list l::oddlinenldbl tl,然后是第二种情况,它成功了!我非常感谢你的解释!