簡體   English   中英

F# - 使用序數等級對序列進行排序

[英]F# - Sort Sequence Using Ordinal Ranks

我有一個由 CsvProvider 生成的序列:

RD;RT;RC;RDT;RG;H;HA;HS;RSP;RFP;RCT;RPZ;HR;HT;RCID
Schema="String,String,String,String,String,String,int,String,String,String,int,String,int,String,String"

在“e:int”position 中可能包含相等的等級。

module SOQN =

   open System

   let ordinalRanks input =
      input
      // |> Seq.sortBy (fun (_, _, _, _, e, _) -> e)
      |> Seq.groupBy (fun (a, b, c, _, e, _) -> (a, b, c, e))
      |> Seq.mapi (fun i a b c d e f -> (a, b, c, d, i + 1, f))

   [<EntryPoint>]
   let main() = 
      let input = seq [ (2107, "HVST", "1315", "Alpha", 1, "JS");
                        (2107, "HVST", "1315", "Beta", 2, "ASC");
                        (2107, "HVST", "1315", "Gamma", 2, "ASC");...
                        (2237, "ABCD", "0905", "Pi", 1, "ABC");
                        (2237, "ABCD", "0905", "Sigma", 1, "CDE");
                        (2237, "ABCD", "0905", "Delta", 2, "EFG");...
                      ]

      let output = ordinalRanks input
      printfn "%A" output

// Actual Output
// seq [ (2107, "HVST", "13-15", "Alpha", 1, "JS");
//       (2107, "HVST", "13-15", "Beta", 2, "ASC");
//       (2107, "HVST", "13-15", "Gamma", 2, "ASC");...] 
//       (2237, "ABCD", "0905", "Pi", 1, "ABC");
//       (2237, "ABCD", "0905", "Sigma", 1, "CDE");
//       (2237, "ABCD", "0905", "Delta", 2, "EFG");...

// Expected Output
// seq [ (2107, "HVST", "13-15", "Alpha", 1, "JS");
//       (2107, "HVST", "13-15", "Beta", 2, "ASC");
//       (2107, "HVST", "13-15", "Gamma", 3, "ASC");...]
//       (2237, "ABCD", "0905", "Pi", 1, "ABC");
//       (2237, "ABCD", "0905", "Sigma", 2, "CDE");
//       (2237, "ABCD", "0905", "Delta", 3, "EFG");...
//

如何使用Ordinal Ranks進行排序。 請注意,排名在由前三個位置確定的組內。 請指教?

// RD;RT;RC;RDT;RG;H;HA;HS;RSP;RFP;RCT;RPZ;HR;HT;RCID
let sortedData (inputCsv: String) = 
    let csvInput = Sample2Sort.Load(inputCsv)
    let csvHeaders = [| sprintf "%s" ((csvInput.Headers.Value) |> String.concat ";") |]
    let csvOutput = 
        csvInput.Rows
        |> Seq.filter (fun row -> row.RFP > 0)
        |> Seq.sortBy (fun row -> (DateTime.Parse(row.RD)), row.RC, row.RT, row.RFP)
        // |> Seq.groupBy (fun (a, b, c, _, _, _) -> (a, b, c))
        |> Seq.groupBy (fun (a, b, c, _, _, _) -> (row.RD, row.RC, row.RT))
        // |> Seq.collect (fun (_, group) -> group |> Seq.mapi (fun i (a, b, c, d, _, f) -> a, b, c, d, i + 1, f))
        |> Seq.collect (fun (_, group) -> 
            group |> Seq.mapi (fun i (a, b, c, d, _, f) -> 
                row.RCID, row.RC, ((row.RD, " ", row.RT) |> String.Concat)), row.RH, i + 1, row.HT)
    (csvHeaders, csvOutput)

我認為您的方法的主要問題是您沒有正確處理groupBy將值序列轉換為值序列的事實 - 它返回一個組列表,其中每個組包含組中的所有元素。

您第一次使用groupBy是正確的,但我相信您只需要使用a, b, c作為分組鍵。 分組后,您可以使用collect得到一個平面列表作為結果。 您需要在 lambda 中移動您的mapi function 調用並在組的所有元素上運行它:

let ordinalRanks input =
  input
  |> Seq.groupBy (fun (a, b, c, _, _, _) -> (a, b, c))
  |> Seq.collect (fun (_, group) ->
    group |> Seq.mapi (fun i (a, b, c, d, _, f) ->
        a, b, c, d, i + 1, f))

我不確定您要如何使用現有訂單e 這個片段只是忽略了它,但它為您的示例輸入提供了正確的結果。

Tomas,我能夠根據您對上述玩具問題的解決方案來解決我的現實問題。

// RD;RT;RC;RDT;RG;H;HA;HS;RSP;RFP;RCT;RPZ;HR;HT;RCID
let sortedData inputCsv = 
    let csvInput = Sample.Load(inputCsv)
    let csvHeaders = [| sprintf "%s" ((csvInput.Headers.Value) |> String.concat ";") |]
    let csvOutput = 
        csvInput.Rows
        |> Seq.filter (fun row -> row.RFP > 0)
        |> Seq.sortBy (fun row -> (DateTime.Parse(row.RD)), row.RC, row.RT, row.RFP)
        |> Seq.groupBy (fun row -> (row.RD, row.RC, row.RT))
        |> Seq.collect (fun (_, group) -> 
            group |> Seq.mapi (fun i row -> 
                               row.RCID, row.RC, 
                               ((row.RD, " ", row.RT) |> String.Concat)), 
                               row.RH, i + 1, row.HT)
    (csvHeaders, csvOutput)

再次感謝您的耐心和您的專業知識。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM