2011-09-18 63 views
3

我認爲有更好的方法來交換列表中的項目([1; 2; 3; 4] - > [2; 1; 4; 3 ]),因爲我爲我的喜好做了太多附加,但我不確定如何最好地做到這一點。交換F#列表中的每一對項目

let swapItems lst = 
    let f acc item = 
     match acc with 
     | [] -> [item] 
     | hd :: next :: tl when tl <> [] -> [next] @ tl @ [item;hd] 
     | _ -> item :: acc 
    List.fold f [] lst 

我該如何改進?這隻適用於長度均勻的列表。

回答

2

這個怎麼樣:

let rec swapItems = function 
    | [] 
    | _::[] as l -> l 
    | a::b::t -> 
     b::a::(swapItems t) 

+3

我認爲這樣做是稍微更優雅'功能| a :: b :: t - > b :: a :: t | a - > failwith「沒有足夠的元素」' –

+0

brillant謝謝,並詛咒F#總是讓事情變得如此簡單;) – Dylan

+0

@jpalmer,我不知道他爲什麼要這樣做,但我推測他也希望這個解決方案能夠處理奇數個元素的列表。 –

1

使用高階函數可以做到這一點爲:

let swapItems l = 
    l |> List.toSeq |> Seq.pairwise 
    |> Seq.mapi (fun i (a,b) -> if i % 2 = 0 then seq [b;a] else Seq.empty) 
    |> Seq.concat |> Seq.toList 
+1

列表是一個seq,你不必調用List.toSeq。我不確定它甚至做了什麼(不止是強制類型檢查器)。 –

3

最簡單的可能的解決方案:

let rec swapItems = function 
    | a::b::xs -> b::a::swapItems xs 
    | xs -> xs 

我喜歡做的是像列表序列變量「複數」的名稱,例如xs而不是x

請注意,這不是尾遞歸,所以如果給它一個很長的列表,它會堆棧溢出。

+1

感謝Jon,這是一個不錯的解決方案,並且更易於閱讀 – Dylan