let dataA3 = [| ("A", 1.0M, -2.0M);
("A", 2.0M, -1.8M);
("A", 3.0M, -1.5M);
("B", 2.0M, -1.5M);
("B", 3.0M, -1.8M);
("C", 1.0M, 2.0M);
("C", 2.0M, 1.8M);
("C", 3.0M, 1.5M) |]
我有一系列元组,我会找到合格的元组。条件是:
第一个字符串元素必须相同3次,在上例中,(“A”,_,_)和(“C”,_,_)是合格的,但是(“B” ,_,_)不是,因为只有2个元组包含“B”;如果相同的第一个元素的数量出现超过3次,则它们也不合格。
第二个小数元素必须按升序排列且大于0.0M;
第三个小数元素必须按升序排列,但可以小于0.0M; 例如:(“A”,1.0M,-2.0M); (“A”,2.0M,-1.8M); (“A”,3.0M,-1.5M)符合此条件;但是(“C”,1.0M,2.0M); (“C”,2.0M,1.8M); (“C”,3.0M,1.5M)不符合此条件,因为2.0M - > 1.8M - > 1.5M按降序排列,而不是按升序排列。
最后,我想获得符合条件的3元组的最后一个元组。在上面的例子中,我想最终的元组是(“A”,3.0M,-1.5M)
let final = [| ("A", 3.0M, -1.5M) |]
如果有更多元组符合条件,我只需要每个不同的第一个字符串元素的3个元组中的最后一个元组。 谢谢,
答案 0 :(得分:4)
对于练习,我从BLUEPIXY的代码中删除了大多数自定义fun
定义。 Seq.reduce也是获取序列中最后一个值的好方法。理解这段代码是好的,不要把它写在生产中。
let tpl3_1 (x,_,_) = x
let tpl3_2 (_,x,_) = x
let tpl3_3 (_,_,x) = x
let isAscendingBy f =
Seq.map f
>> Seq.pairwise
>> Seq.forall ((<||) (<=))
let filter1 =
Seq.groupBy tpl3_1
>> Seq.filter (snd >> Seq.length >> (=) 3)
>> Seq.map snd
let filter2 =
Seq.filter (Seq.forall (tpl3_2 >> (<) 0.0m))
>> Seq.filter (isAscendingBy tpl3_2)
let filter3 =
Seq.filter (isAscendingBy tpl3_3)
let choiceLast =
Seq.reduce (fun _ x -> x)
let final =
filter1
>> filter2
>> filter3
>> Seq.map choiceLast
dataA3 |> final |> printfn "%A"
答案 1 :(得分:3)
let isAscendingBy f sq =
sq
|> Seq.map f
|> Seq.pairwise
|> Seq.forall (fun (x1,x2) -> x1 <= x2)
let filter1 x =
x
|> Seq.groupBy (fun (a,_,_) -> a)
|> Seq.filter (fun (_, g) -> Seq.length g = 3) // than more ? >=
|> Seq.map snd
let filter2 x =
x
|> Seq.filter (fun x -> Seq.forall (fun (_,b,_) -> b >= 0.0m) x)
|> Seq.filter (isAscendingBy (fun (_,b,_) -> b))
let filter3 x =
x
|> Seq.filter (isAscendingBy (fun (_,_,c) -> c))
let choiceLast x =
(x |> Seq.toArray |> Array.rev).[0]
let final = dataA3 |> filter1 |> filter2 |>filter3 |> Seq.toArray |> Array.map choiceLast
答案 2 :(得分:2)
dataA3
|> Seq.groupBy (fun (a,_,_) -> a)
|> Seq.filter (fun (_, d) ->
(d |> Seq.sumBy (fun (_,b,_) -> b)) > 0M
&& (d |> Seq.pairwise |> Seq.forall (fun ((_,x0,x1), (_,y0,y1)) -> x0 < y0 && x1 < y1)))
|> Seq.map (fun (_, d) -> d |> Seq.reduce (fun _ x -> x))
|> Seq.toArray
输出
[|("A", 3.0M, -1.5M)|]
答案 3 :(得分:1)
另一个答案
open System.Collections.Generic
let selectData sq =
let dic = new Dictionary<string, string * decimal * decimal>()
let dicc = new Dictionary<string, int>() //counter
for (key, v1, v2) as v in sq do
if dicc.ContainsKey key then
let (_, oldV1, oldV2) = dic.[key]
if v1 > 0.0M && oldV1 <= v1 && oldV2 <= v2 then
dicc.[key] <- dicc.[key] + 1
dic.[key] <- v //replace new value
elif v1 > 0.0M then
dic.Add(key, v)
dicc.Add(key, 1)
for x in dicc do
if x.Value < 3 then dic.Remove(x.Key) |> ignore
dic.Values |> Seq.toArray
let final = selectData dataA3