我想开始一些关于在F#中简化不同表达式的问题。
任何人都有更好和/或更简单的insertAt实现的想法(参数也可以重新排序)。可以使用列表或序列。
以下是一些开始实施:
let insertAt x xs n = Seq.concat [Seq.take n xs; seq [x]; Seq.skip n xs]
答案 0 :(得分:2)
dannyasher发布的实现是非tail-recursive。为了使函数更有效,我们必须引入一个显式累加器参数,使函数尾递归,并允许编译器优化递归开销:
let insertAt =
let rec insertAtRec acc n e list =
match n, list with
| 0, _ -> (List.rev acc) @ [e] @ list
| _, x::xs -> insertAtRec (x::acc) (n - 1) e xs
| _ -> failwith "Index out of range"
insertAtRec []
答案 1 :(得分:2)
使用Seqs进行尾递归:
let rec insertAt = function
| 0, x, xs -> seq { yield x; yield! xs }
| n, x, xs -> seq { yield Seq.hd xs; yield! insertAt (n-1, x, Seq.skip 1 xs) }
答案 2 :(得分:1)
这是Haskell列表插入的F#实现:
let rec insertAt x ys n =
match n, ys with
| 1, _
| _, [] -> x::ys
| _, y::ys -> y::insertAt x ys (n-1)
let a = [1 .. 5]
let b = insertAt 0 a 3
let c = insertAt 0 [] 3
>
val a : int list = [1; 2; 3; 4; 5]
val b : int list = [1; 2; 0; 3; 4; 5]
val c : int list = [0]
我的Haskell不足以知道在Haskell函数中是否正确处理了传递空列表的情况。在F#中,我们明确地处理了第二个匹配情况中的空列表。
丹尼
答案 3 :(得分:1)
如果您真的想使用序列:
let insertAt x ys n =
let i = ref n
seq {
for y in ys do
decr i
if !i = 0 then yield x
yield y
}
对于所有其他情况,dannyasher的答案肯定更好更快。
答案 4 :(得分:0)
来自Haskell Wiki - http://www.haskell.org/haskellwiki/99_questions/21_to_28
insertAt :: a -> [a] -> Int -> [a]
insertAt x ys 1 = x:ys
insertAt x (y:ys) n = y:insertAt x ys (n-1)
我不是F#程序员所以我不知道F#的等效语法,但这是一个很好的insertAt递归定义