2014-01-25 58 views
0

我正在嘗試編寫一個將列表拆分爲兩個的方法。該函數應返回兩個列表的一個元組,並且該函數採用的參數是第一個列表中的項目數,然後是列表。這裏就是我的意思分割列表F Sharp

列表[1,2,3,4]

分(1,表) - >([1],[2,3,4]) 分(3,列表) - >([1,2,3],[4])

這是我到目前爲止有:

let rec mysplit = function 
    |(n,[])->([],[]) 
    |(1,x::xs)->(x::[],xs) 
    |(n,x::xs)-> mysplit(n-1,xs) 

我不完全知道如何 「捕獲」 的元組回從遞歸呼叫。不知道在哪裏有一個額外的let語句來臨時保存我正在建立的列表。對於語言來說是新的,所以有幾種不同的方法會很好學習。

回答

3

一個簡單的實現將是:

let rec mysplit = function 
    |(n,[])->([],[]) 
    |(1,x::xs)->(x::[],xs) 
    |(n,x::xs)-> let (f, s) = mysplit(n-1,xs) in (x::f, s) 

你也可以寫一尾遞歸版本:

let mysplit (n, l) = 
    let rec mysplit' n' (f, s) = function 
    | [] -> (f, s) 
    | (x::xs) as l' -> if n' = 0 then (f, l') else mysplit' (n'-1) (x::f, xs) xs 

    let (f', s) = mysplit' n ([], []) l in (List.rev f', s) 
0

李的回答顯示了一個可行的解決方案,但回答您的具體問題,你可以捕獲以如下形式返回給您的元組值:

let before, after = mysplit (2, [1;2;3;4;5]) 

您也可以使用這個技巧在一個let語句中聲明多個變量:

let i, j, k = (1, 2, 3) 
6

跳過並帶走這裏是你的朋友。如果有直接的方法,我認爲你不需要做任何匹配或遞歸調用。

let split n l = (l |> Seq.take n, l |> Seq.skip n) 

至於可能的邊緣的情況下,跳過如果在該列表> n元件將返回一個空序列,並採取如果存在序列中< n元件將返回第n個元素。

嘗試在TryFharp.org與您的示例,它按預期工作。

+0

現在,這就是我所說的f# – James