F # Найти квалифицированный последний кортеж из 3 кортежей - PullRequest
1 голос
/ 10 декабря 2011
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) |]

У меня есть массив кортежей, я найду квалифицированные кортежи.Условия:

  1. Первый строковый элемент должен быть одинаковым 3 раза, в приведенном выше примере («A», _, _) и («C», _,_) квалифицированы, но ("B", _, _) нет, так как только 2 кортежа содержат "B";если число одного и того же первого элемента встречается более 3 раз, они также не указываются.

  2. Второй десятичный элемент должен быть в порядке возрастания и быть больше 0,0M;

  3. Третий десятичный элемент должен быть в порядке возрастания, но может быть меньше 0,0M;Например: («А», 1,0М, -2,0М);(«А», 2,0М, -1,8М);(«A», 3,0M, -1,5M) соответствуют данному условию;но ("С", 1,0М, 2,0М);("С", 2,0М, 1,8М);(«C», 3,0M, 1,5M) не подходят для этого условия, поскольку 2,0M -> 1,8M -> 1,5M в порядке убывания, а не в порядке возрастания.

Наконец, я хочу получить последние три набора из трех, которые соответствуют условиям.В приведенном выше примере я хочу, чтобы последний кортеж был («A», 3,0M, -1,5M)

let final = [| ("A", 3.0M, -1.5M) |]

Если для условия есть еще несколько кортежей, мне нужен только последний из 3кортежи для каждого отдельного первого строкового элемента.Спасибо,

Ответы [ 4 ]

4 голосов
/ 10 декабря 2011

Для практики я удалил большинство пользовательских определений fun из кода BLUEPIXY.Также 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"
3 голосов
/ 10 декабря 2011
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 голосов
/ 10 декабря 2011
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)|]
1 голос
/ 10 декабря 2011

Другой ответ

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
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...