Csv F#-使用顺序秩排序序列
我有一个序列,由CsvProvider生成:Csv F#-使用顺序秩排序序列,csv,sorting,f#,ordinal,Csv,Sorting,F#,Ordinal,我有一个序列,由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”位置可能包含相等的列 module SOQN = open System let ordinalRanks
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”位置可能包含相等的列
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");...
//
我认为您的方法的主要问题是您没有正确处理以下事实:
groupBy
将一个值序列转换为一个值序列-它返回一个组列表,其中每个组包含组中的所有元素
您第一次使用groupBy
是正确的,但我相信您只需要使用a、b、c
作为分组键。分组后,您可以使用collect
获得一个简单的列表作为结果。您需要将mapi
函数调用移动到lambda中,并在组的所有元素上运行它:
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
。这段代码只是忽略了它,但它为您的示例输入提供了正确的结果。托马斯,我能够根据您对上述玩具问题的解决方案来解决我的实际问题
// 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)
再次感谢您的耐心和专业知识。我不完全理解这一要求:“请注意,排名是在前三个职位决定的组内。”。例如,如果组中的一个项目有
…“AVST”,“13-15”…
,另一个项目有…“HVST”,“13-15”…
,另一个项目有…“HVST”,“13-10”…
,哪个项目在第一位,基于什么?您可能会发现,首先使用groupBy
函数,按照子组的优先顺序操作子组,然后将其展平,从而更容易对此进行推理。@drkmtr,我对原始代码进行了一些更改,使我获得了所需的排名,但没有返回我预期的顺序?Tomas,你是对的,它解决了我的玩具问题。然而,我遇到的困难是,我正在使用CsvProvider从CSV文件中检索180000条记录,并且需要生成一个seq
,以便继续处理。请参阅原始问题末尾的附加函数sortedData以获得澄清。@matekus我不确定您现在的问题是什么-您能给出一个小的可执行示例来说明问题所在吗?Tomas,在上面的函数sortedData中,我用In>Seq.groupBy(乐趣)替换(a,b,c,,,,)
(a,b,c,,,,->(row.RD,row.RC,row.RT))
例如,我需要输入所有的行列吗?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)存在类似问题@matekus如果您的问题不是关于订购,而是关于使用CSV类型提供程序,那么您应该打开一个新问题-回答如何更改所提供类型中的字段值将不适合在注释中。
// 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)