[英]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.