【问题标题】:Rewrite msort, so it uses pattern matching in F# [duplicate]重写 msort,因此它在 F# 中使用模式匹配 [重复]
【发布时间】:2018-01-21 20:33:25
【问题描述】:

下面的代码是f#中mergesort的代码,我必须重写它,所以它使用了模式匹配。

let rec msort xs =
let sz = List.length xs
        if sz < 2 then xs
        else let n = sz / 2
            let ys = xs.[0..n-1]
            let zs = xs.[n..sz-1]
            in merge (msort ys) (msort zs)

到目前为止,我已经到了这里:

let rec msort (vs: int list) =
    let sz = List.length xs
    match xs with 
    | List.length < 2 -> vs 
    | _ -> 
        let n = sz / 2
        let ys = xs.[0..n-1]
        let zs = xs.[n..sz-1]
        in merge (msort ys) (msort zs)

我似乎找不到更好的方法。有没有人可以帮我上路?

【问题讨论】:

标签: f# pattern-matching


【解决方案1】:

我可能会这样做:

let rec msort (values: int list) =
    let n = values.Length / 2
    if n = 0 
    then values
    else let rec merge (xs: int list) (ys: int list) =
             match (xs, ys) with
             | ([], ys) -> ys
             | (xs, []) -> xs
             | (x :: xs1, y :: ys1) ->
                  if x < y
                  then x :: merge xs1 ys
                  else y :: merge xs ys1        

         let (first, second) = values |> List.splitAt n
         merge (msort first) (msort second)

模式匹配在初始逻辑(列表的长度,长度为 0 和 1 的早期退出)上并不太有用,但我认为它在匹配拆分后的子列表的情况时使其更具可读性。即便如此,msort 部分中只有一个 if/then,如果您真的想要,可以将其替换为模式匹配:

let rec msort (values: int list) =
    match values.Length / 2 with
    | 0 -> values
    | n -> 
        let rec merge (xs: int list) (ys: int list) =
            match (xs, ys) with
            | ([], ys) -> ys
            | (xs, []) -> xs
            | (x :: xs1, y :: ys1) ->
                if x < y
                then x :: merge xs1 ys
                else y :: merge xs ys1        

        let (first, second) = values |> List.splitAt n
        merge (msort first) (msort second)

这在merge 实现中只留下了x&lt;yif/then,我不会改变它。

【讨论】:

    【解决方案2】:

    几乎一样,但我建议自定义拆分:

    let split2 (li: int list) =
        let n = (List.length li) / 2
        let rec looprec (len: int) (l1: int list) (l2: int list) =
             if len > 0 then
                match l1 with 
                   | x::tail -> looprec (len-1) tail (x::l2)
                   | _ -> (List.rev l2, l1)               
             else 
               (List.rev l2, l1)
         in looprec n li []
    
    let rec merge (l1: int list) (l2: int list) =
        match (l1,l2) with
            | (x,[]) -> x
            | ([],y) -> y
            | (x::tx,y::ty) ->
                if x <= y 
                then x::merge tx l2
                else y::merge l1 ty
    
    let rec msort (li: int list) = 
        match li with
            | [] -> []
            | [x] -> [x]
            | _ -> let (l1,l2) = split2 li
                   in merge (msort l1) (msort l2)
    
    let d=  msort [3;20;12]
    
    printfn "%A" d
    

    【讨论】:

      猜你喜欢
      • 2013-10-22
      • 2012-11-25
      • 2017-04-03
      • 2011-10-14
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多