计算F#中元组列表的最小值和最大值

时间:2012-11-26 10:33:30

标签: f#

在F#中,给出 game: (int*int) list 我想计算minx,maxx,miny,maxy每个元组维度的最小值和最大值。

此代码有效但似乎有点笨拙:

let minX (game: (int*int) list) =  game |> List.map (fun (x,y) -> x) |> Seq.min 
let maxX (game: (int*int) list) =  game |> List.map (fun (x,y) -> x) |> Seq.max 
let minY (game: (int*int) list) =  game |> List.map (fun (x,y) -> y) |> Seq.min 
let maxY (game: (int*int) list) =  game |> List.map (fun (x,y) -> y) |> Seq.max 

有任何改进的暗示吗?

4 个答案:

答案 0 :(得分:7)

let minX game = List.minBy fst game |> fst
let maxX game = List.maxBy fst game |> fst
let minY game = List.minBy snd game |> snd
let maxY game = List.maxBy snd game |> snd

答案 1 :(得分:5)

像约翰一样,但更容易阅读:

let game = [(1,4);(2,1)]
let minx,miny,maxx,maxy = 
   game |> List.fold (fun (mx,my,Mx,My) (ax,ay) -> 
             min mx ax, min my ay,
             max Mx ax, max My ay) (Int32.MaxValue,Int32.MaxValue,Int32.MinValue,Int32.MinValue)

答案 2 :(得分:3)

您可以进行一些小改动来改善您的所作所为:

  1. 使用Seq.map代替List.map以避免创建新列表,从而保持内存使用不变
  2. 使用内置的fst / snd函数代替lambdas
  3. 因为game是唯一可以使用函数组合来使代码更简洁的参数
  4. 你最终得到:

    let minX = Seq.map fst >> Seq.min
    let maxX = Seq.map fst >> Seq.max
    let minY = Seq.map snd >> Seq.min
    let maxY = Seq.map snd >> Seq.max
    

    有趣的是,我发现这比pad的解决方案快得多:对于10M元素,0.28对1.75秒。

答案 3 :(得分:2)

pad的答案的折叠版本(只有1个列表遍历)

let minx,miny,maxx,maxy =game |> List.fold (fun (mx,my,Mx,My) (ax,ay) -> 
    let nmx,nMx = if ax<mx then ax,Mx else if ax > Mx then mx,ax else mx,Mx
    let nmy,nMy = if ay<my then ay,My else if ay > My then my,ay else my,My
    nmx,nmy,nMx,nMy) (Int32.MaxValue,Int32.MaxValue,Int32.MinValue,Int32.MinValue)