适用于2个列表的OCaml代码。有没有更好的方法来做到这一点

时间:2012-02-15 02:18:45

标签: list ocaml

我必须迭代2个列表。一个以空子列表的列表开始,第二个列表包含第一个子列表的最大长度。

Example; list1 = [[];[];[];]; list2 = [1;2;3]

我需要填写list1中的空子列表,确保子列表的长度永远不会超过list2中的相应整数。为此,我编写了以下函数,给定一个元素,elem和2两个列表列表和列表,将填写子列表。

let mapfn elem list1 list2= 
    let d = ref 1 in 
        List.map2 (fun a b  -> if ((List.length a) < b) && (!d=1)
                             then  (incr d ; List.append a [elem])
                              else  a )
                        list1 list2

;;

我现在可以在列表的元素上重复调用此函数,并获得我需要的最终答案

此功能按预期工作。但是我对使用int ref d的需要感到困扰。 我有更好的方法来做这件事。

2 个答案:

答案 0 :(得分:4)

我总觉得将问题分成字节大小的部分是值得的,这些部分可以组合在一起形成一个解决方案。您希望将列表填充或截断为给定长度;这很容易分两步完成,先填充,然后截断:

let all x = let rec xs = x :: xs in xs

let rec take n = function
| []           -> []
| _ when n = 0 -> []
| x :: xs      -> x :: take (pred n) xs

all通过重复一个值创建一个无限列表,而take提取最多给定长度的前缀子列表。有了这两个,填充和截断非常简单:

let pad_trim e n l = take n (l @ all e)

(这可能有点令人惊讶,这实际上是在像OCaml这样的严格语言中工作)。根据定义,您所需的功能就是:

let mapfn elem list1 list2 = List.map2 (pad_trim elem) list2 list1

即,将第二个列表作为指定长度的列表,使用提供的填充元素将第一个列表中的每个列表填充到该长度。例如,mapfn 42 [[];[];[]] [1;2;3]给出[[42]; [42; 42]; [42; 42; 42]]。如果这不是您所需要的,您可以调整零件及其组装以满足您的要求。

答案 1 :(得分:3)

你在寻找类似的东西吗?

let fill_list elem lengths =
  let rec fill acc = function
    | 0 -> acc
    | n -> fill (elem :: acc) (n - 1) in
  let accumulators = List.map (fun _ -> []) lengths in
  List.map2 fill accumulators lengths

(* toplevel test *)   
# let test = fill_list 42 [1; 3];;
val test : int list list = [[42]; [42; 42; 42]]

(我无法理解你问题中的第一个空列表列表,但我怀疑它可能是tail-rec fill函数的累加器。)