5

私は次のようなことをします

let last n xs = xs |> List.rev |> Seq.take n |> List.ofSeq |> List.rev

ただし、リストをシーケンスに変換して元に戻すことについてはわかりません。これがF#のやり方ですか?

4

4 に答える 4

5

シーケンス + スキップ

最後の N 個のアイテムを取得することは、最初の (長さ - N) 個のアイテムをスキップすることと同じであるため、入力 (および出力) としてのシーケンスの場合、次のようにすることができます。

let last n xs = Seq.skip ((Seq.length xs) - n) xs

(または、配管を使用して、let last n xs = xs |> Seq.skip (Seq.length xs - n)

入力(および出力)としてのリストの場合、次のことができます。

let last n xs = List.toSeq xs |> Seq.skip (xs.Length - n) |> Seq.toList

または、両方を定義して、シーケンス 1 にパイプするだけです。

let lastList n xs = List.toSeq xs |> last n |> Seq.toList

テール + 再帰

または、(tail) Tail を次のように再帰的に適用することで実現できます。

let rec last n xs =
  if List.length xs <= n then xs
  else last n xs.Tail
于 2013-09-07T05:57:52.897 に答える
3

List.foldBackリストを最後からトラバースするために使用できます。

let takeLast n list = 
    let (_, r) = List.foldBack (fun e (i, acc) -> (i - 1, if i <= 0 then acc else e :: acc)) list (n, [])
    r
于 2013-09-07T09:41:38.320 に答える
0

リストの再構築を避けるために、単純な再帰アルゴリズムを使用できます。

内部的に同じことを行うものも、どちらList.Consも使用していないことに注意してください。Seq.toList

let lastN n xs =
    let rec skip n xs = 
        match n, xs with
        | _, []     -> []   // empty list, returning unchanged
        | 0, _      -> xs   // found an element at which the remainder
                            // of the list is to be returned
        | n', h::t  -> skip (n-1) t    // proceed to next iteration

    let toSkip = (List.length xs) - n  // how many elements to skip
    if toSkip < 0 then xs   // or an exception, depending on expected behavior
    elif toSkip = 0 then xs // requested exactly as many elements
                            // as the list contains
    else skip toSkip xs

// usage
let data = [1 .. 10000000]
let stopWatch = new System.Diagnostics.Stopwatch()
stopWatch.Start()
data
|> lastN 3
|> List.iter (printf "%d ")
stopWatch.Stop()
printfn "\nelapsed: %f ms" stopWatch.Elapsed.TotalMilliseconds

出力:

9999998 9999999 10000000
elapsed: 194.846700 ms
于 2013-09-07T11:05:42.267 に答える