2016-05-12 84 views
3

我想通過前兩個值在集合中找到元組並返回元組的第三個值(或者如果沒有找到,則爲None)。我喜歡這樣的東西:從F#中的元組集合中獲取元素

type Point = (int * int * int) 
type Path = Set<Point> 

let f (x:int) (y:int) (p:Path) : int Option = 
    if Set.exists ((=) (x, y, _z)) p 
    then Some _z 
    else None 

let p:Path = Set.ofList [ (0, 1, 100); (1, 1, 500); (1, 2, 50); ] 

f 1 2 p 

但是這不起作用,因爲顯然,表達式中不允許模式匹配。什麼是正確的方法?謝謝。

+0

基於兩步法的方法有什麼問題? –

+1

什麼是_z' ..? – ildjarn

+0

@John Palmer你是什麼意思?首先,找到元組,然後從中提取值? – Feofilakt

回答

5

您可以將一組列出和使用List.tryFind

let f (x:int) (y:int) (p:Path) : int Option = 
    Set.toList p 
    |> List.tryFind (fun (px, py, _) -> x = px && y = py) 
    |> Option.map (fun (_, _, pz) -> pz) 
+0

我認爲這是最簡單的解決方案 – Feofilakt

1

這是你想要做什麼?

let f (x:int) (y:int) (p:Path) : int Option = 
    match p |> Set.filter (fun (x', y', _) -> x' = x && y' = y) |> Set.toList with 
    | [(_, _, z)] -> Some z 
    | [] -> None 
    | _ -> failwith "More than one point was found!" 

例子:

> let p:Path = Set.ofList [ (0, 1, 100); (1, 1, 500); (1, 2, 50); ];; 

val p : Path = set [(0, 1, 100); (1, 1, 500); (1, 2, 50)] 

> f 1 2 p;; 
val it : Option<int> = Some 50 
+0

可悲的是這是一個有序集合的O(N);如果'Set'具有'lowerBound'函數,它可以是O(logN)... – ildjarn

2

這是fold

let f x y p = Set.fold (function |None -> (fun (x_,y_,z) -> if x=x_ && y=y_ then Some z else None) |f ->fun _ -> f) None p 
+0

這不起作用。它只能有效地檢查集合的最後一個元素。 f 0 1 p返回無 – hvester

+0

@ hvester - 遺忘舊版粘貼 –

5

迭代一個漂亮整潔的解決方案上hvester的回答是:

let f (x:int) (y:int) (p:Path) : int Option = 
    p |> Seq.tryPick (function 
         | x', y', z' when x = x' && y = y' -> Some z' 
         | _ -> None) 

tryPick基本母鹿一步到位發現和映射。