我会做像
这样的事情let last n xs = xs |> List.rev |> Seq.take n |> List.ofSeq |> List.rev
我不确定是否将列表转换为序列然后返回。这是你怎么做的F#?
答案 0 :(得分:3)
获取最后N个项目相当于跳过第一个(长度 - N)项目,因此对于作为输入(和输出)的序列,您可以执行以下操作:
let last n xs = Seq.skip ((Seq.length xs) - n) xs
(或者,使用管道,let last n xs = xs |> Seq.skip (Seq.length xs - n)
和List作为输入(和输出)你可以这样做:
let last n xs = List.toSeq xs |> Seq.skip (xs.Length - n) |> Seq.toList
或通过定义两者,只需将其传递给序列一:
let lastList n xs = List.toSeq xs |> last n |> Seq.toList
或者,这可以通过(尾部)递归地应用Tail来实现:
let rec last n xs =
if List.length xs <= n then xs
else last n xs.Tail
答案 1 :(得分: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
答案 2 :(得分: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
答案 3 :(得分:0)
chamila_c功能的变化: -
/// Returns the last abs(n) items in the specified sequence.
let lastN n xs =
// The number to skip will be negative if n is too large; this will result in 0 items being skipped.
// By taking abs(n), the number to skip can't get too large, and we avoid an exception being thrown.
xs |> Seq.skip (Seq.length xs - abs n)