List 子列表上的操作
我目前想知道一种根据给定标准将列表拆分为子列表的方法。由于本书的教学目的,我不使用内置函数。 即,以下程序应在给定列表的情况下返回列表列表列表,其中每个子列表没有重复项,且按升序排列:List 子列表上的操作,list,recursion,f#,List,Recursion,F#,我目前想知道一种根据给定标准将列表拆分为子列表的方法。由于本书的教学目的,我不使用内置函数。 即,以下程序应在给定列表的情况下返回列表列表列表,其中每个子列表没有重复项,且按升序排列: increment [4;4;10;20;5;30;6;10] = [[4;10;20];[5;30];[6;10]] increment [5;6;4;3;2;1] = [[5;6];[4];[3];[2];[1]] 到目前为止,我最好的尝试是基于我生成的这段代码: let rec increment li
increment [4;4;10;20;5;30;6;10] = [[4;10;20];[5;30];[6;10]]
increment [5;6;4;3;2;1] = [[5;6];[4];[3];[2];[1]]
到目前为止,我最好的尝试是基于我生成的这段代码:
let rec increment li [lo] =
match li with
|[] -> [lo]
|[x] -> [x]::[lo]
|x::y::xs -> if x = y then
increment (y::xs) [lo]
elif x < y then
x::(increment (y::xs) [lo])
else
(x::(increment xs [lo]))::[lo]
让rec增加li[lo]=
与李相配
|[]->[lo]
|[x] ->[x]:[lo]
|x::y::xs->如果x=y,则
增量(y::xs)[lo]
如果x
不幸的是,我未能创建列表列表。这个原则是正确的。它基于我构建的函数,可以正确地隔离升序列表(如果存在):
let rec incrementAux li =
match li with
|[] -> []
|[x] -> [x]
|x::y::xs -> if x = y then
incrementAux (y::xs)
elif x < y then
x::(incrementAux (y::xs))
else
x::(incrementAux [])
let rec incrementAux li=
与李相配
|[] -> []
|[x] ->[x]
|x::y::xs->如果x=y,则
递增辅助(y::xs)
如果x
如有任何建议,将不胜感激 不需要递归就可以完成<代码>列表。折叠和一点内存可以帮助:
let input = [4;4;10;20;5;30;6;10]
let output = [[4;10;20];[5;30];[6;10]]
let increment =
List.fold (fun (last::rest as total) x ->
match last with
| [] -> [x] :: rest
| h::_ as last ->
if x > h then (x::last)::rest
else if x = h then total
else [x]::total) [[]]
>> List.map List.rev
>> List.rev
let testOutput = increment input
testOutput = output // true
如果您不想使用
列表
模块上的内置函数(纯粹作为学习练习),那么您只需要理解映射
和折叠
,就可以自己实现它们。我会先说。您可以方便地在折叠
方面实现rev
,因此这应该不是问题。一旦您了解了每个函数的功能,您可以自己实现它们,如下所示:
let rec fold f state = function
| [] -> state
| head::tail -> fold f (f state head) tail
let map f list =
[for item in list -> f item]
let rev list =
fold (fun acc cur -> cur::acc) [] list
然后,您可以用自己的函数替换Szer解决方案中的内置函数:
let input = [4;4;10;20;5;30;6;10]
let output = [[4;10;20];[5;30];[6;10]]
let increment =
fold (fun (last::rest as total) x ->
match last with
| [] -> [x] :: rest
| h::_ as last ->
if x > h then (x::last)::rest
else if x = h then total
else [x]::total) [[]]
>> map rev
>> rev
let testOutput = increment input
testOutput = output
注意,
fold
的这种实现方式与F#List
的实现方式不同。这是基于维基百科文章中简单的Haskell示例。功能是相同的,但实现是完全不同的,因为F#实际上使用可变累加器和for循环。谢谢您的回答。我对一种不使用内置函数的方法更感兴趣,这样可以更好地理解fsharp编程的更基本的元素。