这是我到目前为止所做的:
type u = {str : string} //some type that has some property str (for simplicity, only one)
type du=
| A of u
| B of u // some discriminated union that carries u with it
然后,在某个地方,我有一个du序列,我正在做distinctBy和属性做的不同是str。 我能想出的最好的是:
Seq.distinctBy (fun d -> match d with (A u|B u) -> u.str)
代码有效,但我不喜欢必须匹配有区别的联盟的a和b,并希望用某些东西替换匹配。
问题是,什么? :)编辑:
在我的情况下,被区分的联合的a和b将始终带有相同的类型u,一个解决方案是摆脱du并添加它的字符串形式输入u并简化整个混乱,但我想现在保持这种方式,因为我打算在a和b上做匹配...
答案 0 :(得分:5)
作为du的财产,这次比赛怎么样?
type u = {str : string}
type du =
| A of u
| B of u with
member this.U =
match this with
(A u | B u) -> u
[A {str="hello"}; B {str="world"}; A {str="world"}]
|> Seq.distinctBy (fun x -> x.U.str)
//val it : seq<du> = seq [A {str = "hello";}; B {str = "world";}]
然而,我有一些想法可以更好地塑造你和你之间的关系,同时满足你的“编辑”问题。一种方法是简单地使用元组:
type u = {str : string}
type du =
| A
| B
//focus on type u
[A, {str="hello"}; B, {str="world"}; A, {str="world"}]
|> Seq.distinctBy (fun (_,x) -> x.str)
//val it : seq<du * u> = seq [(A, {str = "hello";}); (B, {str = "world";})]
//focus on type du
let x = A, {str="hello"}
match x with
| A,_ -> "A"
| B,_ -> "B"
//val it : string = "A"
另一种方法是切换它并将du添加到u:
type du =
| A
| B
type u = { case : du; str : string}
//focus on type u
[{case=A; str="hello"}; {case=B; str="world"}; {case=A; str="world"}]
|> Seq.distinctBy (fun x -> x.str)
//val it : seq<u> = seq [{case = A;
// str = "hello";}; {case = B;
// str = "world";}]
//focus on type du
let x = {case=A; str="hello"}
match x with
| {case=A} -> "A"
| {case=B} -> "B"
//val it : string = "A"
答案 1 :(得分:2)
你真的不能像你描述的那样简化它,但你可以简化它。 谢谢@Tomas Petricek
[ A { str = "A" }; B { str = "B" }; B { str = "B" } ]
|> Seq.distinctBy (fun (A u | B u) -> u.str)
|> Seq.toArray;;
<强>输出强>
[| A {str = "A";}; B {str = "B";} |]
答案 2 :(得分:2)
我对F#有点新鲜,但希望这会有所帮助。在我看来,Active Patterns可能会让您的生活更轻松,以减少您在模式匹配中输入的内容。而不是使用A a | B b你可以在它的位置使用活动模式AorB。
type u = { str : string }
type du =
| A of u
| B of u
let (|AorB|) (v:du) =
match v with
| A a -> a
| B b -> b
[A { str = "A" }; B { str = "B"}; A { str = "A"}]
|> Seq.distinctBy (fun d ->
match d with
| AorB s -> s)
|> Seq.iter (fun i -> match i with AorB c -> printfn "%s" c.str)
随着斯蒂芬的加法,最后的表达可以写成。
[A { str = "A" }; B { str = "B"}; A { str = "A"}]
|> Seq.distinctBy (|AorB|)
|> Seq.iter (fun i -> match i with AorB c -> printfn "%s" c.str)