I would do something like
我会做一些类似的事情
let last n xs = xs |> List.rev |> Seq.take n |> List.ofSeq |> List.rev
I am not sure about turning a list to a sequence and back though. Is this how you do it F#?
我不确定是否要把一个列表转换成一个序列,然后再返回。你就是这样做的吗?
4 个解决方案
#1
3
You could use List.foldBack
to traverse the list from the end:
您可以使用列表。回到最后遍历列表:
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
3
Seq + Skip
Taking the last N items is equivalent to skipping the first (length - N) items, so for a Sequence as input (and output), you could do something like:
取最后的N项相当于跳过第一个(长度- N)项,因此对于一个序列作为输入(和输出),您可以做如下操作:
let last n xs = Seq.skip ((Seq.length xs) - n) xs
(or, with piping, let last n xs = xs |> Seq.skip (Seq.length xs - n)
(或者,有管道,让n xs = xs |> Seq。跳过(Seq。长度xs - n)
and for a List as input (and output) you could do:
对于作为输入(和输出)的列表,您可以这样做:
let last n xs = List.toSeq xs |> Seq.skip (xs.Length - n) |> Seq.toList
or by defining both, just pipe it to the sequence one:
或者通过定义两者,把它们连接到序列1:
let lastList n xs = List.toSeq xs |> last n |> Seq.toList
Tail + Recursion
Alternatively, this can be achieved by (tail) recursively applying Tail as so:
或者,这可以通过(tail)递归地应用tail来实现:
let rec last n xs =
if List.length xs <= n then xs
else last n xs.Tail
#3
0
To avoid rebuilding the list, you may use a simple recursive algorithm.
为了避免重新构建列表,您可以使用一个简单的递归算法。
Note, we are not using neither List.Cons
nor Seq.toList
which does the same internally.
注意,我们没有使用这两个列表。缺点和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
Output:
输出:
9999998 9999999 10000000
elapsed: 194.846700 ms
#4
0
Variation on chamila_c's function:-
变化在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)
#1
3
You could use List.foldBack
to traverse the list from the end:
您可以使用列表。回到最后遍历列表:
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
3
Seq + Skip
Taking the last N items is equivalent to skipping the first (length - N) items, so for a Sequence as input (and output), you could do something like:
取最后的N项相当于跳过第一个(长度- N)项,因此对于一个序列作为输入(和输出),您可以做如下操作:
let last n xs = Seq.skip ((Seq.length xs) - n) xs
(or, with piping, let last n xs = xs |> Seq.skip (Seq.length xs - n)
(或者,有管道,让n xs = xs |> Seq。跳过(Seq。长度xs - n)
and for a List as input (and output) you could do:
对于作为输入(和输出)的列表,您可以这样做:
let last n xs = List.toSeq xs |> Seq.skip (xs.Length - n) |> Seq.toList
or by defining both, just pipe it to the sequence one:
或者通过定义两者,把它们连接到序列1:
let lastList n xs = List.toSeq xs |> last n |> Seq.toList
Tail + Recursion
Alternatively, this can be achieved by (tail) recursively applying Tail as so:
或者,这可以通过(tail)递归地应用tail来实现:
let rec last n xs =
if List.length xs <= n then xs
else last n xs.Tail
#3
0
To avoid rebuilding the list, you may use a simple recursive algorithm.
为了避免重新构建列表,您可以使用一个简单的递归算法。
Note, we are not using neither List.Cons
nor Seq.toList
which does the same internally.
注意,我们没有使用这两个列表。缺点和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
Output:
输出:
9999998 9999999 10000000
elapsed: 194.846700 ms
#4
0
Variation on chamila_c's function:-
变化在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)