Код OCaml, который работает на 2 списках.Есть ли лучший способ сделать это - PullRequest
3 голосов
/ 15 февраля 2012

Я должен перебрать 2 списка.Один начинается как список пустых подсписков, а второй имеет максимальную длину для каждого из подсписков, находящихся в первом.

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

Мне нужно заполнить пустые подсписки в списке1, гарантируя, чтодлина подсписков никогда не превышает соответствующего целого числа в list2.С этой целью я написал следующую функцию, которая с учетом элемента, elem и 2 два списка list и list, заполнит подсписки.

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 ]

4 голосов
/ 15 февраля 2012

Я всегда считаю целесообразным разбить проблему на куски размером в байты, которые можно объединить для формирования решения. Вы хотите дополнить или усечь списки до заданной длины; это легко сделать в два шага, сначала pad, а затем усечь:

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]]. Если это не то, что вам нужно, вы можете настроить детали и их сборку в соответствии с вашими требованиями.

3 голосов
/ 15 февраля 2012

Вы ищете что-то подобное?

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.)

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...