// val reverse : l:'a list -> 'a list
let reverse l =
let rec reverseInner l acc =
match l with
| x::xs ->
let acc = x :: acc
reverseInner xs acc
| [] -> acc
reverseInner l []
// val split : l:'a list -> 'a list * 'a list
let split l =
let listMid = (int)((length l)/2)
let rec splitInner l index counter list1 list2 =
match (l,counter) with
| (x::xs,c) ->
if c < index then
let list1 = x :: list1
let counter = counter + 1
splitInner xs index counter list1 list2
else
let list2 = x :: list2
let counter = counter + 1
splitInner xs index counter list1 list2
| ([], _) -> ((reverse list1), (reverse list2))
splitInner l listMid 0 [] []
split [1;2;3;4;5;6;7;8;9;10]
val it : int list * int list = ([1; 2; 3; 4; 5], [6; 7; 8; 9; 10])
split [1;2;3;4;5;6;7;8;9;10;11]
val it : int list * int list = ([1; 2; 3; 4; 5], [6; 7; 8; 9; 10; 11])
另一個變化來自RosettaCode
let split list =
let rec aux l acc1 acc2 =
match l with
| [] -> (acc1,acc2)
| [x] -> (x::acc1,acc2)
| x::y::tail ->
aux tail (x::acc1) (y::acc2)
in aux list [] []
這一個是如何工作的。
比賽有三種模式
| [] which only matches when the input list is empty
| [x] which only matches when there is only one item in the list
| x::y::tail which matches all the other patterns
這一個說,我們並不需要知道列表的長度,因爲如果我們在列表中至少有兩個項目| x::y::tail
然後把一個在列表中的一個和另一個在名單二。重複此操作直到列表中有一個或沒有項目。如果列表中有一個項目放入第一個列表並重復。現在輸入列表是空的,所以返回兩個列表。
第三變化從fssnip.net
let splitList divSize lst =
let rec splitAcc divSize cont = function
| [] -> cont([],[])
| l when divSize = 0 -> cont([], l)
| h::t -> splitAcc (divSize-1) (fun acc -> cont(h::fst acc, snd acc)) t
splitAcc divSize (fun x -> x) lst
由Joel Huang其使用Continuation-passing style
這一個傳遞到內功能的功能。功能是(fun x -> x)
,內部函數在cont
參數中接收它。這個也有三種匹配模式。
| [] only matches on empty list
| l only matches on list with one item
| h::t matches when there are two or more items in the list.
但是因爲它是傳遞一個函數每次遞歸調用,即建立了功能的評價不計算,直到完成正在通過遞歸函數傳遞的列表。它也使用一個計數器,但倒計數到0以避免必須傳遞額外的參數。這是高級編碼,所以不要花很多時間去理解它,但要知道,因爲函數是一流的,所以這是可能的。
第四個變化從TheInnerLight - posted就在前一天。
let split lst =
let rec helper lst l1 l2 ctr =
match lst with
| [] -> l1, l2 // return accumulated lists
| x::xs ->
if ctr%2 = 0 then
helper xs (x::l1) l2 (ctr+1) // prepend x to list 1 and increment
else
helper xs l1 (x::l2) (ctr+1) // prepend x to list 2 and increment
helper lst [] [] 0
我如何創建拆分。
與格式開始
let funXYZ list =
let rec funXYZInner list acc =
match list with
| head :: tail ->
let acc = (somefunc head) :: acc
funXYZInner tail acc
| [] -> acc
funXYZInner list []
名稱的功能拆分
let split list =
let rec splitInner l acc =
match l with
| head :: tail ->
let acc = (somefunc head) :: acc
splitInner tail acc
| [] -> acc
split list []
現在我知道我需要一個輸入列表,並在一個元組中的兩個輸出列表中的兩個輸出列表
let split l =
let rec splitInner l list1 list2 =
match l with
| head :: tail ->
let list1 = (somefunc head)
let list2 = (somefunc head)
splitInner tail list1 list2
| [] -> (list1, list2)
split l [] []
由於拆分會將列表分成兩半,這可以在迭代t之前計算通過列表
let split l =
let listMid = (int)((length l)/2)
let rec splitInner l list1 list2 =
match l with
| head :: tail ->
let list1 = (somefunc head)
let list2 = (somefunc head)
splitInner tail list1 list2
| [] -> (list1, list2)
split l [] []
爲了把這變成一個條件,我們需要一個計數器。因此,將計數器初始化爲splitInner l listMid 0 [] []
中的0
並將其傳遞給匹配模式。因爲對於最後的匹配模式,我們不在乎計數的值是多少,所以使用_
。
我們還需要知道什麼來比較反對,這是listMid
所以通過到splitInner
。
也增加計數器爲每個使用的頭。
let split l =
let listMid = (int)((length l)/2)
let rec splitInner l listMid counter list1 list2 =
match (l ,counter) with
| (head :: tail, c) ->
let list1 = (somefunc head)
let list2 = (somefunc head)
let counter = counter + 1
splitInner tail listMid counter list1 list2
| ([],_) -> (list1, list2)
splitInner l listMid 0 [] []
現在添加條件
let split l =
let listMid = (int)((length l)/2)
let rec splitInner l listMid counter list1 list2 =
match (l,counter) with
| (head :: tail, c) ->
if c < listMid then
let list1 = head :: list1
let counter = counter + 1
splitInner tail listMid counter list1 list2
else
let list2 = head :: list2
let counter = counter + 1
splitInner tail listMid counter list1 list2
| ([],_)-> (list1, list2)
splitInner l listMid 0 [] []
重命名head
到x
和tail
到xs
作爲個人喜好
let split l =
let listMid = (int)((length l)/2)
let rec splitInner l listMid counter list1 list2 =
match (l,counter) with
| (x::xs, c) ->
if c < listMid then
let list1 = x :: list1
let counter = counter + 1
splitInner xs listMid counter list1 list2
else
let list2 = x :: list2
let counter = counter + 1
splitInner xs listMid counter list1 list2
| ([],_)-> (list1, list2)
splitInner l listMid 0 [] []
,並將其送回作爲結果前反向列表。
let split l =
let listMid = (int)((length l)/2)
let rec splitInner l listMid counter list1 list2 =
match (l, counter) with
| (x :: xs, c) ->
if c < listMid then
let list1 = x :: list1
let counter = counter + 1
splitInner xs listMid counter list1 list2
else
let list2 = x :: list2
let counter = counter + 1
splitInner xs listMid counter list1 list2
| ([],_)-> (reverse list1, reverse list2)
splitInner l listMid 0 [] []
我認爲你輸入一個列表並返回兩個列表的元組。缺少的是決定在哪裏拆分列表的值或計數。如果它是一個計數,那麼兩個列表是一個有效的輸出。如果分割的值是字符串中的字符,則輸出可能是多個列表。請舉例說明輸入和輸出列表。 :) –
對於Edit3,你有'splitInner(1 0 [] [])'你需要'splitInner 1 0 [] []'注意這些parens被丟棄。你正在傳遞一個元組到curried參數。我知道你使用元組很多;我更喜歡咖喱參數,因爲它們在功能性編程方面效果更好。當他們有意義時,我使用元組。 –
你將不得不要求mergesort作爲一個單獨的問題。這一個已經成爲分裂的問題。 –