Splitting a list of items into two lists of odd and even indexed items

前端 未结 8 2076
悲&欢浪女
悲&欢浪女 2020-12-11 00:56

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, g

相关标签:
8条回答
  • 2020-12-11 01:27

    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
    
    0 讨论(0)
  • 2020-12-11 01:34

    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:

    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.

    Good luck!

    0 讨论(0)
  • 2020-12-11 01:43

    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 
    
    0 讨论(0)
  • 2020-12-11 01:45

    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
    
    0 讨论(0)
  • 2020-12-11 01:47

    Implementation which does not stack-overflows:

    let splitList list = List.foldBack (fun x (l,r) -> x::r, l) list ([],[])
    
    0 讨论(0)
  • 2020-12-11 01:51

    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
    
    0 讨论(0)
提交回复
热议问题