F#排序元组数组

时间:2011-12-04 16:55:15

标签: f# functor applicative

let standard = (0, 4.5M, 4L)
let tuples = [| ("A", -2, 1.0M, 2L); 
                ("B", -1, 2.0M, 3L); 
                ("C", 0, 3.0M, 4L); 
                ("D", 1, 4.0M, 5L); 
                ("E", 2, 5.0M, 6L) |]
let qualified = tuples
              |> Array.sortBy(fun (_, a, b, c) -> (a, -b, c))
              |> Array.filter(fun (_, a, b, c) -> (a, b, c) <= standard)
printfn "%A" qualified

我有一系列元组和一个标准。我想对元组进行排序,并选择那些符合要求的元组 对于元组,我忽略了第一个元素,并以普通方式对第二个元素和第四个元素进行排序,但也以相反的顺序对第三个元素进行排序;我有一个标准元组,因为所有带有第二个元素的元组至少与标准元素一样大,而第三个元素最多只能与标准元素一样大。 在上面的例子中,合格的元组是:= [| (“C”,0,3.0M,4L)|] 条件是:第二元素&gt; = 0并且第三元素&lt; = 4.5M和第四元素&gt; = 4L 但我的代码不起作用! 让我知道如何写一个函数可以做这个工作! 谢谢,周末愉快。 约翰

2 个答案:

答案 0 :(得分:3)

我认为没有任何聪明的方法可以使用对元组有效的内置比较来完成所需的操作。主要问题是比较将第一个元素视为最重要的元素,因此它决定仅使用前几个元素(甚至不考虑其余的值。您的条件指定对所有元素的限制。所以,古斯塔沃的解决方案可能是最简单的方法。

但是,有一些小问题 - 首先,在排序之前执行过滤可能是一个好主意,因为那时你的排序功能需要排序更少的元素:

 let qualified = 
   tuples 
   |> Array.sortBy (...) 
   |> Array.filter (...)

如果你想在一些易于改变的全局值中表示条件,那么创建一个具有3个值的元组来指定所需的最小值/最大值是不够的,因为你没有说这个值是最小值还是maximum ...但是,您可以使用指定条件的函数元组:

let standard = ((fun _ -> true), (<=) 0, (>=) 4.5M, (<=) 4L) 

这指定第一个元素的所有值都是OK,第二个元素的值应该大于零((<=) 0代表一个带x并返回0 <= x的函数)等然后你可以写:

let conditionsHold (p1, p2, p3, p4) (v1, v2, v3, v4) = 
  p1 v1 && p2 v2 && p3 v3 && p4 v4

let qualified = 
  tuples 
  |> Array.sortBy(fun (_, a, b, c) -> (a, -b, c)) 
  |> Array.filter (conditionsHold standard)

答案 1 :(得分:2)

只需更改最后一行:

Array.filter(fun (_, a, b, c) -> let (x,y,z) = standard in a >= x && b <= y && c >= z)

请注意,元组(“D”,1,4.0M,5L)也符合条件。

更新:

Tomas是对的,最好先过滤。 解决它的另一个有趣的功能方法可能是使3-uple成为一个应用函数。

let pure' x = (x,x,x)
let (<*>) (f,g,h) (x,y,z) = (f x, g y, h z)

let standard = (0, 4.5M, 4L)
let tuples = [| ("A", -2, 1.0M, 2L); 
                ("B", -1, 2.0M, 3L); 
                ("C", 0, 3.0M, 4L); 
                ("D", 1, 4.0M, 5L); 
                ("E", 2, 5.0M, 6L) |]
let qualified = tuples              
              |> Array.filter(fun (_, a, b, c) -> ((>=),(<=),(>=)) <*> (a,b,c) <*> standard = pure' true)
              |> Array.sortBy(fun (_, a, b, c) -> (a, -b, c))