有没有办法找到列表列表的最大值? 例如
word = 'busboi'
guesses = 'bs'
word.tr('^'+guesses, '-')
# => "b-sb--"
将输出:^
答案 0 :(得分:2)
我正在考虑使用模式匹配,但它似乎是噩梦般的
let rec lmax list = match list with
| [] -> None
| x :: xs -> Pervasives.max (Some x) (lmax xs)
但该函数不是尾递归的。 函数参数之间的评估顺序是未定义的,但基本上你计算这样的事情:
-> Evaluate (Some x)
-> Evaluate (lmax xs)
...recursion...
<- Then, compute max
我们必须计算并记住每次调用lmax
的中间值。
另一种方法是使用辅助递归函数aux
,它采用累加器值acc
:
let lmax list =
let rec aux list acc = match list with
| [] -> acc
| x :: xs -> (aux xs (Pervasives.max acc (Some x)))
in (aux list None)
然后,我们不需要存储中间值:
-> Evaluate xs
-> Compute max of current acc with (Some x)
-> ...recursion...
递归调用将计算当前值的结果,不需要记住中间值,这使得递归调用迭代。
以上是一种常见的模式,可以通过高阶函数抽象出来,称为 fold (或 reduce )。有两种 fold :上面的第一种是右侧折叠,带有累加器的那种是左侧折叠。
它们采用reduce函数,该函数根据先前的结果和值以及初始结果(对于空列表)计算新结果。
当reduce函数关联时,两种折叠计算相同的结果,并且由于其尾递归实现,建议尽可能使用左折叠。
当缩减函数为右关联时,使用右侧折叠,如cons
。以下是List.map
的重新实现:
let my_map fn list = List.fold_right (fun x xs -> (fn x) :: xs) list []
因此,您可以使用左侧折叠计算列表的最大值:
let lmax list =
List.fold_left
(fun max x -> Pervasives.max max (Some x))
None
list
option
类型是必要的,因为空列表没有最大值(您也可以返回最大的负整数)。
现在,您还可以使用折叠计算列表列表的最大值:
let llmax list =
List.fold_left
(fun max list -> Pervasives.max max (lmax list))
None
list;;
对于列表列表中的每个元素,我们计算得到lmax
的最大值并生成到目前为止看到的最大值。
llmax [[1; 2; 3; -4; -2; 0]; [1; 2; -5; -3; -1]]
- : int option = Some 3
如果要概括,可以编写一个foldmax
函数,该函数由一个函数参数化,该函数计算列表元素的最大值:
let foldmax fn list =
List.fold_left
(fun max x -> Pervasives.max max (fn x))
None
list
val foldmax : ('a -> 'b option) -> 'a list -> 'b option = <fun>
最后,您可以使用此辅助功能重写lmax
,llmax
(lllmax
等):
let lmax list = foldmax (fun x -> Some x) list
let llmax list = foldmax lmax list
let lllmax list = foldmax llmax list
答案 1 :(得分:1)
在命令式/过程式语言中,您可以遍历列表并与最大数字进行比较,即
def max(lst):
max = None
for l in lst:
for x in l:
if max is None or x > max:
max = x
return max
(显然不是惯用的,只是尽可能明确这一点)
在OCaml中,你会做类似的事情,但使用一种称为“折叠”(一种函数)的东西,这是对上述想法的抽象。
let max list =
let f max x =
match max with
| None -> Some x
| Some m -> if m > x then Some m else Some x
in
List.fold_left f None (List.flatten list)
答案 2 :(得分:0)
let max l =
List.fold_left (fun max x ->
Pervasives.max max (Some x)
) None (List.flatten l)
<强>测试强>
# max [[1; 2; 3; -4; -2; 0]; [1; 2; -5; -3; -1]];;
- : int option = Some 3
# max [];;
- : 'a option = None
<强>评论强>
Pervasives.max发现最多两个选项:
# Pervasives.max None (Some (-1));;
- : int option = Some (-1)
List.flatten:连接列表列表
# List.flatten [[1; 2; 3; -4; -2; 0]; [1; 2; -5; -3; -1]];;
- : int list = [1; 2; 3; -4; -2; 0; 1; 2; -5; -3; -1]