2

次のような整数のリストを使用します。

[1;2;3;4;5;6;7;8;9]

上記のintのリストのリストを作成するにはどうすればよいですか?すべての新しいリストは同じ指定された長さです。

たとえば、次の場所から移動する必要があります。

[1;2;3;4;5;6;7;8;9] to [[1;2;3];[4;5;6];[7;8;9]]

分割する数は3ですか?

御時間ありがとうございます。

4

4 に答える 4

3

したがって、実際に必要なのは型の関数です

val split : int list -> int -> int list list

整数のリストとサブリストサイズを取ります。さらに一般的なものはどうですか?

val split : 'a list -> int -> 'a list list

実装は次のとおりです。

let split xs size =
  let (_, r, rs) =
    (* fold over the list, keeping track of how many elements are still
       missing in the current list (csize), the current list (ys) and
       the result list (zss) *) 
    List.fold_left (fun (csize, ys, zss) elt ->
      (* if target size is 0, add the current list to the target list and
         start a new empty current list of target-size size *)
      if csize = 0 then (size - 1, [elt], zss @ [ys])
      (* otherwise decrement the target size and append the current element
         elt to the current list ys *)
      else (csize - 1, ys @ [elt], zss))
      (* start the accumulator with target-size=size, an empty current list and
         an empty target-list *)
        (size, [], []) xs
  in
  (* add the "left-overs" to the back of the target-list *)
  rs @ [r]

これで加点できたら教えてください!;)

于 2012-11-07T21:27:19.313 に答える
2

私はおそらくこのようにします:

    let split lst n =
      let rec parti n acc xs = 
        match xs with 
        | []              -> (List.rev acc, [])
        | _::_ when n = 0 -> (List.rev acc, xs)
        | x::xs -> parti (pred n) (x::acc) xs
      in let rec concat acc = function
        | [] -> List.rev acc
        | xs -> let (part, rest) = parti n [] xs in concat (part::acc) rest
      in concat [] lst

が均等にn分割されない場合は寛大であることに注意してください。List.length lst例: split [1;2;3;4;5] 2与える[[1;2];[3;4];[5]]

最後の注意: OCaml の標準ライブラリは非常に骨の折れるものであるため、コードは非常に冗長です:/ 別のライブラリを使用すると、これをより簡潔にすることができると確信しています。

于 2012-11-07T03:20:27.013 に答える
2

あなたが与えるコードは、リストの先頭から指定された数の要素を削除する方法です。進める方法の 1 つは、この関数をそのままにして (おそらく少しクリーンアップして)、外部関数を使用してリスト全体を処理することです。これを簡単に行うために、関数はリストの残りの部分も返す必要があるかもしれません (そのため、外側の関数はまだセグメント化する必要があるものを簡単に判断できます)。

ただし、単一の関数で問題を解決したいようです。もしそうなら、欠けている主なものは、すでに切り取った部分のアキュムレータです。また、カウントに達したときに終了することはできません。切り取ったばかりの部分を覚えてから、リストの残りを同じ方法で処理する必要があります。

これを自分で解決する場合は、問題を一般化して、再帰呼び出しがすべての場合に役立つようにします。うまくいくかもしれないことは、最初の部分を残りよりも短くすることです. そうすれば、アキュムレータなし (再帰呼び出しのみ) の単一の関数として記述できます。

于 2012-11-07T02:37:24.463 に答える
1
let rec split n xs =
  let rec take k xs ys = match k, xs with
    | 0, _ -> List.rev ys :: split n xs
    | _, [] -> if ys = [] then [] else [ys]
    | _, x::xs' -> take (k - 1) xs' (x::ys)
  in take n xs []
于 2012-11-08T07:36:30.247 に答える