C# Linq 字典 IO

C# Linq Dictionary IO

如何使用 LinQ 执行此操作?

我有一个 txt 文件。(大约有 100 行。)

6 7
0/3 # ##t#kon tu#i#do#b#n ko#yk####a#s##ttak###lk##ul$$$$#$#$$$####$$$$#$$$$$$#$$#$$$$$#$

我把它存储在字典中(两行)。

alap = File.ReadAllLines("veetel.txt");
Dictionary<string,string> statisztikaDictionary = new Dictionary<string,string>();
for (int z = 1; z < alap.Length; z+=2)
{
     statisztikaDictionary.Add(alap[z],alap[z-1]);
}

第一行,6 是记录的日期,7 是记录的人员 ID。 我需要创建一个关于它的统计数据。 像这样写出来:

Day:Number of persons who made a record.

我数了一下,所以人数和日期值在 0-11 之间变化,但我们 "don't" 知道这一点。 第二行以 0/3 开头,表示 0 成人 3 儿童。我需要每天读取 2 个值和一个 ID,并打印出该人观察到的狼数量(在本例中为 3)。 我正在为期末考试进行培训,但我被困住了。任何帮助都会得到帮助,

我猜你更喜欢一些指导而不是工作代码作为完整的解决方案。

为了能够在字典中查询某一天记录观察的人数,并查询某个人在某一天观察到的狼的数量,我将创建一个字典,其键由以下组成day 和 personId 和 value 作为观察数据。

请参阅下面的示例,其中 2 类 用于保存字典的键和值。

对于键:

public class ObservationId
{
    public int Day;
    public int PersonId;

    public ObservationId(int day, int personId)
    {
        this.Day = day;
        this.PersonId = personId;
    }
    public ObservationId(string line)
    {
        // Add code here to split data in the line to fill day and personId values
    }
}

对于值:

public class ObservationData
{
    public int Adults;
    public int Childs;
    public int TotalWolves
    {
        get { return this.Adults + this.Childs; }
    }
    public ObservationData(int adults, int childs)
    {
        this.Adults = adults;
        this.Childs = childs;
    }
    public ObservationData(string line)
    {
        // Add code here to split data in the line to fill values for adults and childs (and optionally the rest of data)
    }
}

从文件中填充数据:

        string[] alap;
        alap = File.ReadAllLines("veetel.txt");
        Dictionary<ObservationId, ObservationData> statisztikaDictionary = new Dictionary<ObservationId, ObservationData>();
        for (int z = 1; z < alap.Length; z += 2)
        {
            ObservationId id = new ObservationId(alap[z - 1]);
            ObservationData data = new ObservationData(alap[z]);
            statisztikaDictionary.Add(id, data);
        }

要按日期和人 ID 搜索:

    public int GetTotalWolves(int day, int personId)
    {
        ObservationId id = new ObservationId(day, personId);
        if (statisztikaDictionary.ContainsKey(id))
        {
            return statisztikaDictionary[id].TotalWolves;
        }
        else
        {
            return 0;
        }
    }

要搜索一天(使用 Linq):

    public int GetObservationsByDay(int day)
    {
        return statisztikaDictionary.Where(o => o.Key.Day == day).Count();
    }

我建议创建可以 hold/store 相关数据的自定义 class。让它成为 Statisztika 和以下 fields/properties:DayPersonIdVisitorCountOfVisits

Statisztika class 定义:

public class Statisztika
{
    private int iday = 0;
    private int ipersonid = 0;
    private int ivisitor =0;
    private int icount =0;

    //class constructor
    public Statisztika(string[] twolines)
    {
        iday = Convert.ToInt32(twolines[0].Split(' ')[0]);
        ipersonid = Convert.ToInt32(twolines[0].Split(' ')[1]);
        //we have to replace these lines:
        //ivisitor = Convert.ToInt32(twolines[1].Split('/')[0]);
        //icount = Convert.ToInt32(twolines[1].Split('/')[1].Split(' ')[0]);
        //with:
        //check for single slash
        int pos = twolines[1].IndexOf("/");
        if (pos>-1)
        {
            //in case of error TryParse method returns zero
            Int32.TryParse(twolines[1].Substring(0,pos)
                .Replace("#", "").Trim(), out ivisitor);
            Int32.TryParse(twolines[1].Substring(pos+1,2)
                .Replace("#","").Trim(), out icount);
        }
    }

    public int Day
    {
        get {return iday;}
        set {iday = value;}
    }

    public int PersonId
    {
        get {return ipersonid;}
        set {ipersonid = value;}
    }

    public int Visitor
    {
        get {return ivisitor;}
        set {ivisitor = value;}
    }

    public int CountOfVisits
    {
        get {return icount;}
        set {icount = value;}
    }
}

如您所见,要创建 Statisztika 对象,您需要传递两行文本(来自文件)才能启动字段。现在,我们需要创建 List<Statisztika>。想象一下,它是数据容器。要从此列表中获取数据,我们可以使用 Linq 查询。

用法:

string sFileName = @"D:\veetel.txt";
string[] alap = File.ReadAllLines(sFileName);

List<Statisztika> stat = new List<Statisztika>();
for(int i=0; i<alap.Length; i+=2)
{
    //Linq rules! 
    string[] twolines = alap.Skip(i).Take(2).ToArray();
    //create new Statisztika object and add to list
    stat.Add(new Statisztika(twolines));
}

//use create linq query, group data by day and visitor type ;)
var qry = stat
    .GroupBy(p=>new{p.Day, p.Visitor})
    .Select(grp=>new
            {
                Day = grp.Key.Day,
                Visitor = grp.Key.Visitor,
                SumOfVisits = grp.Sum(p=>p.CountOfVisits)
            })
    .OrderBy(a=>a.Day)
    .ThenBy(a=>a.Visitor);

Console.WriteLine("Day Visitor SumOfVisits");
foreach(var sta in qry)
{
    Console.WriteLine("{0}\t{1}\t{2}", sta.Day, sta.Visitor, sta.SumOfVisits);
}

示例输出:

Day Visitor SumOfVisits
1  0  0
2  0  0
2  1  0
3  0  0
3  2  15
4  0  0
5  0  0
6  0  12
7  0  9
7  1  9
8  0  0
9  0  0
9  1  0
10  0  0
11  0  0
11  1  0
11  3  0
11  13  0

[编辑]

注意:如果 \(斜杠)不存在,Statisztika class 构造函数在 VisitorCountOfVisits fields/members 中使用零.

如果您想检查代码是否正常工作,请使用此代码:

string sFileName = @"D:\veetel.txt";
    string[] alap = File.ReadAllLines(sFileName);
    for(int i=0; i<alap.Length; i+=2)
    {
        int one = 0;
        int two = 0;
        string[] twolines = alap.Skip(i).Take(2).ToArray();
        int pos = twolines[1].IndexOf("/");
        if(pos>-1)
        {
            Int32.TryParse(twolines[1].Substring(0,pos)
                     .Replace("#", "").Trim(), out one);
            Int32.TryParse(twolines[1].Substring(pos+1,2)
                     .Replace("#","").Trim(), out two);
        }
        Console.WriteLine("{0}\t{1}\t{2}", 
                      twolines[1].Substring(0,8), one, two);
    }

以上代码产生如下输出:

#abor# #  0  0
ta###t##  0  0
0/# a #a  0  0
a pat#k#  0  0
e#zakrol  0  0
1/3#sot#  1  3
0/# a pa  0  0
#3/0#s#t  3  0
verofe#y  0  0
ta#o#t#v  0  0
eszakro#  0  0
#/3#so##  0  3
...etc.

干杯,Maciej