我想開始一些關於簡化F#中不同表達式的問題。insertAt in F#更簡單和/或更好
任何人都有更好和/或更簡單的insertAt實現的想法(參數也可以重新排序)。可以使用列表或序列。
下面是一些開始實施:
let insertAt x xs n = Seq.concat [Seq.take n xs; seq [x]; Seq.skip n xs]
我想開始一些關於簡化F#中不同表達式的問題。insertAt in F#更簡單和/或更好
任何人都有更好和/或更簡單的insertAt實現的想法(參數也可以重新排序)。可以使用列表或序列。
下面是一些開始實施:
let insertAt x xs n = Seq.concat [Seq.take n xs; seq [x]; Seq.skip n xs]
實施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 []
模式匹配使得這種情況下的代碼更加複雜。我尋求更短,更簡單的實現。 – 2009-07-22 12:18:44
你也問過更好的解決方案......你的問題非常簡單。 – Dario 2009-07-22 12:25:41
從哈斯克爾維基 - 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
是的,我從那裏得到了測驗。但我試圖在F#中實現它。所以我想在F#中找到比我更簡單的實現。我在Haskell中得到的最簡單的是: insertAt x xs n = take n xs ++ [x] ++ drop n xs 但是這不是最優的。可能是一些簡單而優化的Haskell回答將會是: insertAt x xs n = let(before,after)= splitAt n xs in before ++ [x] ++ after – 2009-07-22 08:51:35
下面是一個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#中,我們明確地處理第二個匹配情況下的空列表。發佈
丹尼
對於情況下,你真的想與序列一起工作:
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的答案是明確更好,更快。
使用尾遞歸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) }
有許多很好的回答這個問題已經是,但我想提醒大家,我覺得這個功能很可能是很少有用;大多數情況下,您可能會使用insertAt,這些算法/實現可以通過mutables和System.Collections.Generic.List或某些鍵值數據結構更好地提供。 – Brian 2009-07-22 16:54:40