将项目列表分割为奇数项和偶数项的两个列表

时间:2022-05-24 22:06:11

I would like to make a function that accepts a list and returns two lists: the first contains every odd item, and the second contains every even item.

我想让一个函数接受一个列表并返回两个列表:第一个包含每个奇数项,第二个包含每个偶数项。

For example, given [1;2;4;6;7;9], I would like to return [ [1;4;7] ; [2;6;9] ].

例如,给定[1;2;4;6;7;9],我想返回[[1;4;7];(2、6、9])。

I have written this so far and I do not know how to progress.

到目前为止,我一直在写这篇文章,我不知道该怎么写。

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 [] []

8 个解决方案

#1


38  

Implementation which does not stack-overflows:

不堆叠的实现:

let splitList list = List.foldBack (fun x (l,r) -> x::r, l) list ([],[])

#2


11  

If you mean odd and even values for positions of items, here is a (non-tail-recursive) solution:

如果你指的是奇数和偶数的值,这里有一个(非尾部递归的)解决方案:

let rec splitList = function
    | [] -> [], []
    | [x]-> [x], []
    | x1::x2::xs -> let xs1, xs2 = splitList xs
                    x1::xs1, x2::xs2

#3


6  

Here is a straightforward non-recursive solution:

这里有一个简单的非递归解决方案:

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

Being applied to your sample it yields exactly what you wanted:

应用到你的样本中,它会产生你想要的结果:

splitList [1;2;4;6;7;9];;

val it : int list list = [[1; 4; 7]; [2; 6; 9]]

#4


2  

It looks like this is what you were going for, which is indeed a nice way to do it as it's tail-recursive.

看起来这就是你想要的,这确实是一个很好的方法因为它是尾部递归的。

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


2  

Another (less efficient) option

另一个(效率低)选项

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 ]

If you want to avoid creating temporary lists, consider using sequences:

如果你想避免创建临时列表,考虑使用序列:

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

Yet, another one, similar to Daniel's version:

然而,另一个与丹尼尔的版本相似:

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

#6


1  

Sounds like you want List.partition<'T> ( http://msdn.microsoft.com/en-us/library/ee353782.aspx ). This function takes a predicate and a list and will return a pair (2-tuple) where the first element is all the elements that passed your test and the second is all the elements that did not pass the test. So you could classify odds and evens with:

听起来你想要列表。分区< >(http://msdn.microsoft.com/en-us/library/ee353782.aspx)。该函数接受一个谓词和一个列表,并返回一对(2元组),其中第一个元素是通过测试的所有元素,第二个元素是没有通过测试的所有元素。所以你可以把几率和概率分为:

List.partition odd [1;2;4;6;7;9]

If your really want a list, you can use fst and snd to extract the elements from the tuple and put them in a list.

如果您确实想要一个列表,您可以使用fst和snd从元组中提取元素并将它们放入列表中。

Good luck!

好运!

#7


1  

My 2¢, in OCaml, since there still is a bounty open.

我的2¢OCaml,因为还有赏金是敞开的。

Maybe you could give us a hint what you want. Elegance? FP? Tail recursion? Performance?

也许你可以给我们一个提示。优雅?《外交政策》吗?尾递归?性能?

Edit:

编辑:

I removed the longer solution. For List.partition to work, the predicate was missing. Here it is:

我去掉了较长的解。为列表。为了使分区正常工作,谓词丢失了。这里是:

let so_split lst = 
  let flag = ref false in
  List.partition (fun e -> flag := not !flag; !flag) lst

Improvements any? Testing the solution:

改进吗?测试解决方案:

# so_split [1;2;4;6;7;9];;
- : int list * int list = ([1; 4; 7], [2; 6; 9])

#8


0  

Just for completeness here is a boring, more imperative solution:

为了完整起见,这里有一个无聊的、更必要的解决方案:

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 

#1


38  

Implementation which does not stack-overflows:

不堆叠的实现:

let splitList list = List.foldBack (fun x (l,r) -> x::r, l) list ([],[])

#2


11  

If you mean odd and even values for positions of items, here is a (non-tail-recursive) solution:

如果你指的是奇数和偶数的值,这里有一个(非尾部递归的)解决方案:

let rec splitList = function
    | [] -> [], []
    | [x]-> [x], []
    | x1::x2::xs -> let xs1, xs2 = splitList xs
                    x1::xs1, x2::xs2

#3


6  

Here is a straightforward non-recursive solution:

这里有一个简单的非递归解决方案:

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

Being applied to your sample it yields exactly what you wanted:

应用到你的样本中,它会产生你想要的结果:

splitList [1;2;4;6;7;9];;

val it : int list list = [[1; 4; 7]; [2; 6; 9]]

#4


2  

It looks like this is what you were going for, which is indeed a nice way to do it as it's tail-recursive.

看起来这就是你想要的,这确实是一个很好的方法因为它是尾部递归的。

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


2  

Another (less efficient) option

另一个(效率低)选项

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 ]

If you want to avoid creating temporary lists, consider using sequences:

如果你想避免创建临时列表,考虑使用序列:

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

Yet, another one, similar to Daniel's version:

然而,另一个与丹尼尔的版本相似:

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

#6


1  

Sounds like you want List.partition<'T> ( http://msdn.microsoft.com/en-us/library/ee353782.aspx ). This function takes a predicate and a list and will return a pair (2-tuple) where the first element is all the elements that passed your test and the second is all the elements that did not pass the test. So you could classify odds and evens with:

听起来你想要列表。分区< >(http://msdn.microsoft.com/en-us/library/ee353782.aspx)。该函数接受一个谓词和一个列表,并返回一对(2元组),其中第一个元素是通过测试的所有元素,第二个元素是没有通过测试的所有元素。所以你可以把几率和概率分为:

List.partition odd [1;2;4;6;7;9]

If your really want a list, you can use fst and snd to extract the elements from the tuple and put them in a list.

如果您确实想要一个列表,您可以使用fst和snd从元组中提取元素并将它们放入列表中。

Good luck!

好运!

#7


1  

My 2¢, in OCaml, since there still is a bounty open.

我的2¢OCaml,因为还有赏金是敞开的。

Maybe you could give us a hint what you want. Elegance? FP? Tail recursion? Performance?

也许你可以给我们一个提示。优雅?《外交政策》吗?尾递归?性能?

Edit:

编辑:

I removed the longer solution. For List.partition to work, the predicate was missing. Here it is:

我去掉了较长的解。为列表。为了使分区正常工作,谓词丢失了。这里是:

let so_split lst = 
  let flag = ref false in
  List.partition (fun e -> flag := not !flag; !flag) lst

Improvements any? Testing the solution:

改进吗?测试解决方案:

# so_split [1;2;4;6;7;9];;
- : int list * int list = ([1; 4; 7], [2; 6; 9])

#8


0  

Just for completeness here is a boring, more imperative solution:

为了完整起见,这里有一个无聊的、更必要的解决方案:

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