F # Arrays - входные массивы для вывода Seq of Seqs - PullRequest
0 голосов
/ 07 мая 2018

У меня есть три массива, которые, когда первые два выровнены - [| ("C", "No"), ("C", "Yes"); ... |] - и отфильтрованы по третьему, должны генерировать "seq of seqs" - [...; seq [("C", ("Нет", 1), ("Да", 1)]; ...] ;:

module SOQN = 

   open System

   let first    = [| "C"; "D"; "C"; "E"; "B"; "A"; "A"; "E"; "A"; "B"; "A"; "D"; "B"; "E" |]
   let second   = [| "No"; "No"; "Yes"; "Yes"; "Yes"; "No"; "Yes"; "No"; "Yes"; "Yes"; "Yes"; "Yes"; "Yes"; "No" |]
   let fltr     = [| "No"; "Yes" |]

   let filterProduct (first:string[]) (second:string[]) (fltr:string) = 
      Array.zip first second
      |> Array.filter (fun (_, s) ->
         Seq.forall (fun c -> s.Contains (string c)) fltr)
      |> Array.map fst
      |> Array.reduce (fun acc item -> acc + ", " + item)

   let third = 
      [for i in [0..fltr.Length - 1] do
         yield (filterProduct first second fltr.[i])]
      |> List.toArray

   printfn "third: %A" third

  // Expected Result: third: [seq [("A", ("No", 1), ("Yes", 3)]; 
  //                          seq [("B", ("No", 0), ("Yes", 3)]; 
  //                          seq [("C", ("No", 1), ("Yes", 1)]; 
  //                          seq [("C", ("No", 1), ("Yes", 1)];
  //                          seq [("C", ("No", 2), ("Yes", 1)]]

  // Actual Result:   third: [|"C, D, A, E, E"; "C, E, B, A, A, B, A, D, B"|]

Как мне получить ожидаемый результат?

Ответы [ 3 ]

0 голосов
/ 08 мая 2018

Что ж, основываясь на комментариях во включенном коде, вы ожидаете увидеть данные Seq >, где ... является критической точкой. К сожалению, вы не сможете сделать это таким образом, потому что если вы проверяете элементы своей внутренней последовательности, вы использовали это: («A», («No», 1), («Yes», ​​3). Во-первых, отсутствуют пропущенные закрывающие скобки (не так уж и сложно), во-вторых, внутренний seq имеет смешанные типы: первый элемент - строка, второй и третий - кортеж string и int.

Немного изменив ожидаемый результат, вы можете добиться чего-то подобного следующим образом:

let first    = [| "C"; "D"; "C"; "E"; "B"; "A"; "A"; "E"; "A"; "B"; "A"; "D"; "B"; "E" |]
let second   = [| "No"; "No"; "Yes"; "Yes"; "Yes"; "No"; "Yes"; "No"; "Yes"; "Yes"; "Yes"; "Yes"; "Yes"; "No" |]
let fltr     = [| "No"; "Yes" |]

let filterProduct (first:string[]) (second:string[]) (fltrs:string []) = 
    Array.zip first second
    |> Array.groupBy fst
    |> Array.map (fun (k, values) ->
        k,
            fltrs
            |> Array.map (fun fltr ->
                let c = values |> Array.map snd |> Array.filter (fun x -> x = fltr) |> Array.length
                fltr, c
            )
    )
    |> Array.sortBy (fun (k, v) -> k)

let third = 
    filterProduct first second fltr

printfn "third: %A" third

Таким образом, third имеет следующий формат:

seq<string * seq<string * int>>

0 голосов
/ 20 мая 2018

Я не уверен, хотите ли вы видеть ноль, да или нет. Если нет, следующий код может помочь.

namespace FSharpBasics

module Classifier =

    let private first    = 
        [| "C"; "D"; "C"; "E"; "B"; "A"; "A"; "E";
        "A"; "B"; "A"; "D"; "B"; "E" |]
    let private second   = 
        [| "No"; "No"; "Yes"; "Yes"; "Yes"; "No"; "Yes"; "No";
        "Yes"; "Yes"; "Yes"; "Yes"; "Yes"; "No" |]
    //let private fltr     = 
    //    [| "No"; "Yes" |]

    (* operations *)
    let pair =
        Array.zip

    let classifier =
        let intermediate =
            pair first second

        let result = 
            intermediate
            |> Seq.groupBy (fun (first, _) -> first)
            |> Seq.map (fun (first, grouping) -> 
                (first, grouping 
                        |> Seq.groupBy (fun (_, second) -> second)
                        |> Seq.map (fun (second, grouping) ->
                            (second, grouping
                                     |> Seq.length))))
        seq {
            for x in result do yield x
        }

    [<EntryPoint>]
    let main argv =
        classifier |> Seq.iter (printfn "%A")
        System.Console.ReadKey() |> ignore
        0

(* ---Result----

("C", seq [("No", 1); ("Yes", 1)])
("D", seq [("No", 1); ("Yes", 1)])
("E", seq [("Yes", 1); ("No", 2)])
("B", seq [("Yes", 3)])
("A", seq [("No", 1); ("Yes", 3)])

---- ----*)
0 голосов
/ 08 мая 2018

Это близкое приближение к тому, что я хотел!

module SOANS = 

  open System

  let first        = [| "C"; "D"; "C"; "E"; "B"; "A"; "A"; "E"; "A"; "B"; "A"; "D"; "B"; "E" |]
  let firstFilter  = [| "A"; "B"; "C"; "D"; "E" |]
  let second       = [| "No"; "No"; "Yes"; "Yes"; "Yes"; "No"; "Yes"; "No"; "Yes"; "Yes"; "Yes"; "Yes"; "Yes"; "No" |]
  let secondFilter = [| "No"; "Yes" |]

  let filterProduct (first:string[]) (second:string[]) (secondFilter:string) = 
     Array.zip first second
     |> Array.filter (fun (_, s) ->
        Seq.forall (fun c -> s.Contains (string c)) secondFilter)
     |> Array.map fst
     |> Array.toSeq

  let third = 
     [for i in [0..firstFilter.Length - 1] do
        yield (filterProduct second first firstFilter.[i])]
     |> List.countBy id
     |> List.toSeq

  let fourth = 
     third
     |> Seq.map (fun (s, _) -> s |> (Seq.countBy id) |> Seq.sort)

  printfn ""
  printfn "fourth:"
  fourth |> Seq.iter (fun (c) -> (printf "%A; " c))

  // Expected Result: fourth: [seq [("A", ("No", 1), ("Yes", 3)]; 
  //                           seq [("B", ("No", 0), ("Yes", 3)]; 
  //                           seq [("C", ("No", 1), ("Yes", 1)]; 
  //                           seq [("C", ("No", 1), ("Yes", 1)];
  //                           seq [("C", ("No", 2), ("Yes", 1)]]
  // Actual Result:   fourth: seq [("No", 1); ("Yes", 3)]; 
  //                          seq [("No", 0); ("Yes", 3)]; 
  //                          seq [("No", 1); ("Yes", 1)]; 
  //                          seq [("No", 1); ("Yes", 1)]; 
  //                          seq [("No", 2); ("Yes", 1)];
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...