2

在 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

4 回答 4

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
于 2012-11-26T10:41:19.633 回答
5

像约翰的,但更容易阅读:

let game = [(1,4);(2,1)]
let minx, miny, maxx, maxy =
    let folder (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), game) ||> List.fold folder
于 2012-11-26T12:21:49.903 回答
3

你可以做一些小的改变来改善你所拥有的:

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

你最终得到:

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 秒。

于 2012-11-26T16:53:40.813 回答
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)
于 2012-11-26T11:04:53.763 回答