如何在c#中将csv文件分组并从中制作嵌套字典?

我有一个csv文件,我想用它制作一个嵌套的字典。该文件如下所示:

FilmMaker,MovieTitle,EndDate
FunnyM,F1,20191210
FunnyM,F2,20191211
FunnyM,F3,20191212
FunnyM,F4,20191213
FunnyM,F5,20191214
SadM,S1,20191210
SadM,S2,20191211
SadM,S3,20191212
SadM,S4,20191213
SadM,S5,20191214
ScaryM,C1,20191210
ScaryM,C2,20191211
ScaryM,C3,20191212
ScaryM,C4,20191213
ScaryM,C5,20191214

我想按FilmMaker 1)分组,按EndDate 2)分类,3)选择在2019年12月10日之后结束的电影,以及4)仅选择最早的第二个结尾。然后,我想5)制作一个字典,其关键字为MovieTitle,并且另两列为值。结果将如下所示:

new_dictionary = {'F3': {'FilmMaker':'FunnyM','EndDate':20191012},'S3': {'FilmMaker':'SadM','C3': {'FilmMaker':'ScaryM','EndDate':20191012} }

我已经上网查询了,但是我找不到如何在多个条件下用csv文件制作嵌套字典的方法。到目前为止,这是我发现的:

Dictionary<string,string[]> result = File.ReadLines("movies.csv")
                                            .Skip(1)
                                            .Select(line => line.Split(','))
                                            .GroupBy(arr => arr[0])              
                                            .ToDictionary(gr => gr.Key,gr => gr.Select(s => s[1]).ToArray());

我认为应该有OrderByWhere,并且字典必须设置为Dictionary<string,Dictionary<string,string>> dic_movies = new Dictionary<string,string>>();,但我不知道如何完全完成它。

wslqfm 回答:如何在c#中将csv文件分组并从中制作嵌套字典?

您需要修剪列。

.Select(line => line.Split(',').Select(s => s.Trim()).ToList())

遵循说明

  

如何通过EndDate对它们进行排序,并仅为每个组获取第n个值,而不是特定日期值?

此处是遵循问题概述步骤的版本。

var data = @"FilmMaker,MovieTitle,EndDate
    FunnyM,F1,20191210
    FunnyM,F2,20191211
    FunnyM,F3,20191212
    FunnyM,F4,20191213
    FunnyM,F5,20191214
    SadM,S1,20191210
    SadM,S2,20191211
    SadM,S3,20191212
    SadM,S4,20191213
    SadM,S5,20191214
    ScaryM,C1,20191210
    ScaryM,C2,20191211
    ScaryM,C3,20191212
    ScaryM,C4,20191213
    ScaryM,C5,20191214";

var d = data.Split("\r\n")
    .Skip(1)
    .Select(line => line.Split(',').Select(s => s.Trim()).ToList())
    .Select( a => new { FilmMaker = a[0],MovieTitle = a[1],EndDate= DateTime.ParseExact(a[2],"yyyyMMdd",CultureInfo.InvariantCulture)}) // No error handling for brevity
    // We have crossed the csv/object boundary

    // 1) group them by FilmMaker 
    .GroupBy( o => o.FilmMaker )       
    // 2) sort them by EndDate
    // 3) select movies that ends after 2019-12-10
    // 4) select only that ends the second earliest
    // NOTE: This is quite fragile - if there is no 2nd earliest movie this will throw
    .Select( g => new { FilmMaker = g.Key,Movie = g.Where( m => m.EndDate > new DateTime(2019,12,10)).OrderBy( m => m.EndDate).Skip(1).First() })
    // 5) make a dictionary that has keys as MovieTitle and also has other two columns as values. 
    .ToDictionary( m => m.Movie.MovieTitle,m => new { FilmMaker = m.FilmMaker,EndDate = m.Movie.EndDate.ToString("yyyyMMdd")});


    Console.WriteLine(System.Text.Json.JsonSerializer.Serialize(d));
{
"F3":{"FilmMaker":"FunnyM","EndDate":"20191212"},"S3":{"FilmMaker":"SadM","C3":{"FilmMaker":"ScaryM","EndDate":"20191212"}
}
,

您可以将CSV转换为中间类,然后在创建最终词典之前将其用于处理。这将使您能够将问题分解为多个步骤并提高可读性。例如,

public class Movie
{
    public string FilmMaker{get;set;}
    public string MovieTitle{get;set;}
    public DateTime EndDate{get;set;}
}

假设电影类的定义如上所述,您可以按以下方式将CSV排序到字典。

var csvCollection = csv.Split(new []{Environment.NewLine},StringSplitOptions.RemoveEmptyEntries)
                                    .Skip(1)
                                    .Select(line => line.Split(',').Select(c=>c.Trim()).ToList());

var movieCollection = csvCollection.Select(x=> new Movie
                                           { 
                                               FilmMaker = x[0],MovieTitle = x[1],EndDate = DateTime.ParseExact(x[2],CultureInfo.InvariantCulture)
                                           });

var result = movieCollection.Where(x=> x.EndDate> new DateTime(2019,10))
                                .OrderBy(x=>x.EndDate)
                                .GroupBy(x=>x.FilmMaker)
                                .Select(x=> x.Skip(1).First())
                                .ToDictionary(key=>key.MovieTitle,value=>new []{$"FilmMaker:{value.FilmMaker}",$"EndDate:{value.EndDate.Year}{value.EndDate.Month}{value.EndDate.Day}"});

输出

enter image description here

,

使用诸如CsvHelper之类的库来解析csv,请勿手动执行。

一旦您读完记录,就只需要过滤,排序,分组和选择所需的结果即可。

ID,Name,Result,Device
1,John,Success,Windows
2,Felix,Fail,Windows
3,Suzie,Windows
4,Angie,Windows,Waiting,IOS,Retry,5,Michel,Mac,6,Robert,Windows
7,James,
本文链接:https://www.f2er.com/3155191.html

大家都在问