我想创建一个接受列表并返回两个列表的函数:第一个包含每个奇数项,第二个包含每个偶数项。
例如,给定[1;2;4;6;7;9]
,我想返回[ [1;4;7] ; [2;6;9] ]
。
到目前为止我写过这篇文章,我不知道如何进步。
let splitList list =
let rec splitOdd oList list1 list2 =
match oList with
| [] -> []
| head :: tail -> splitEven tail (list1::head) list2
and splitEven oList list1 list2 =
match oList with
| [] -> []
| head :: tail -> splitOdd tail list1 (list2::head)
splitOdd list [] []
答案 0 :(得分:39)
没有堆栈溢出的实现:
let splitList list = List.foldBack (fun x (l,r) -> x::r, l) list ([],[])
答案 1 :(得分:11)
如果你的意思是项目位置的奇数和偶数值,这里是一个(非尾递归)解决方案:
let rec splitList = function
| [] -> [], []
| [x]-> [x], []
| x1::x2::xs -> let xs1, xs2 = splitList xs
x1::xs1, x2::xs2
答案 2 :(得分:6)
这是一个简单的非递归解决方案:
let splitList ll =
ll
|> List.mapi (fun i x -> (i % 2 = 0, x))
|> List.partition fst
|> fun (odd,even) -> [List.map snd odd, List.map snd even];;
val splitList : 'a list -> 'a list list
应用于您的样本,它可以产生您想要的结果:
splitList [1;2;4;6;7;9];;
val it : int list list = [[1; 4; 7]; [2; 6; 9]]
答案 3 :(得分:2)
另一个(效率较低)选项
let splitList xs =
let odd, even =
xs
|> List.zip [ 1 .. (List.length xs) ]
|> List.partition (fun (i, _) -> i % 2 <> 0)
[ odd |> List.map snd; even |> List.map snd ]
如果您想避免创建临时列表,请考虑使用序列:
let splitListSeq xs =
xs
|> Seq.mapi (fun i x -> (i % 2 = 0, x))
|> Seq.groupBy (fun (b, _) -> b)
|> Seq.map snd
|> Seq.map ((Seq.map snd) >> Seq.toList)
|> Seq.toList
然而,另一个,类似丹尼尔的版本:
let splitListRec xs =
let rec loop l r = function
| [] -> [l; r]
| x::[] -> [x::l; r]
| x::y::t -> loop (x::l) (y::r) t
loop [] [] xs |> List.map List.rev
答案 4 :(得分:2)
看起来这就是你想要的,这确实是一种很好的方式,因为它是尾递归的。
let splitList items =
let rec splitOdd odds evens = function
| [] -> odds, evens
| h::t -> splitEven (h::odds) evens t
and splitEven odds evens = function
| [] -> odds, evens
| h::t -> splitOdd odds (h::evens) t
let odds, evens = splitOdd [] [] items
List.rev odds, List.rev evens
答案 5 :(得分:1)
听起来你想要List.partition&lt;'T&gt; (http://msdn.microsoft.com/en-us/library/ee353782.aspx)。此函数接受谓词和列表,并返回一对(2元组),其中第一个元素是通过测试的所有元素,第二个元素是未通过测试的所有元素。因此,您可以使用以下方法对赔率和赔率进行分类:
List.partition odd [1;2;4;6;7;9]
如果您真的想要一个列表,可以使用fst
和snd
从元组中提取元素并将它们放在列表中。
答案 6 :(得分:1)
我的2¢,在OCaml中,因为仍有赏金开放。
也许你可以给我们一个暗示你想要的东西。优雅? FP?尾递归?性能
修改强>
我删除了较长的解决方案。要使List.partition工作,谓词就丢失了。 这是:
let so_split lst =
let flag = ref false in
List.partition (fun e -> flag := not !flag; !flag) lst
改进了吗?测试解决方案:
# so_split [1;2;4;6;7;9];;
- : int list * int list = ([1; 4; 7], [2; 6; 9])
答案 7 :(得分:0)
为了完整起见,这是一个无聊,更迫切的解决方案:
let splitList (list:int list) =
let odds = [for i in 0..list.Length-1 do
if i%2=1 then
yield list.[i]]
let evens = [for i in 0..list.Length-1 do
if i%2=0 then
yield list.[i]]
odds,evens