有效的数据结构可以保存员工的活动?

时间:2015-11-13 18:34:29

标签: c# data-structures

我在存储员工的目录中有n个excel文件'一个月内每天的活动。它们有三列:日期,活动和类别。我不需要这个类别。

我想基本上读取n个excel文件并输出一个word文档,该文档有效地按日期排序每位员工的所有活动,例如:

第1天至第5天:

第一天:
员工#1:
- 任务一 - 任务b
-Task c

员工#2:
- 任务一 - 任务b
- 任务c
...

第2天: ...
...
...
第7天至第11天:
... ...

我想知道我可以用什么数据结构来有效地保存这些信息,这样我就可以轻松地编写我想要的文档。现在,我使用一个字符串数组来保存每个excel行,并将它们存储在List中,然后我将其存储在每个员工的字典中,密钥是每个员工的用户名。

虽然我认为这些数据结构本身是有效的,但它们对我的主要目标来说并不友好,即打印每位员工每天订购的数据,因此密钥本身应该是日期。

回顾一下:正在使用的当前数据结构:

Dictionary<string,List<string[]>> dictActividades = new     Dictionary<string,List<string[]>>();

每个员工的Excel文件中的所有行都存储在List中。 我真的不需要字典功能,因为我可以按顺序阅读所有内容。我一看到员工的excel文件就可以打印但是我必须立刻读取n个excel文件(尽管n非常小)

思想?

编辑:这是我现在所拥有的:

        string directorioActividades = @"\\mar-fp01\mar_tecnologia$\Coordinacion de Apoyo a Usuarios\Informes\" + 
            fechaInicio.Year.ToString() + "\\" + fechaInicio.Year.ToString() + "-" + 
            fechaInicio.Month.ToString().PadLeft(2, '0');

        string[] archivos = Directory.GetFiles(directorioActividades, "*.xlsx");
        Dictionary<string,List<string[]>> dictActividades = new Dictionary<string,List<string[]>>();
        for (int j = 0; j < archivos.Length; j++)
        {
            List<string[]> actividades = new List<string[]>();
            string nombreArchivo = Path.GetFileNameWithoutExtension(archivos[j]);
            String excelConnectionString = @"Provider=Microsoft.ACE.OLEDB.12.0;" +
                "Data Source=" + archivos[j] + ";" +
                "Extended Properties=Excel 8.0; ";
            using (OleDbConnection con = new OleDbConnection(excelConnectionString))
            {
                OleDbCommand command = new OleDbCommand("Select * From [Actividades$]", con);
                con.Open();

                OleDbDataReader dr = command.ExecuteReader();
                int cantidadcolumnas = dr.FieldCount;

                string tipodatos = null;
                string[] filaDatos = new string[cantidadcolumnas];
                while (dr.Read())
                {
                    for (int k = 0; k < cantidadcolumnas; k++)
                    {
                        tipodatos = dr.GetFieldType(k).ToString();
                        if (tipodatos == "System.Int32")
                        {
                            filaDatos[k] = dr.GetInt32(k).ToString();
                        }
                        if (tipodatos == "System.String")
                        {
                            filaDatos[k] = dr.GetString(k);
                        }
                        if (tipodatos == "System.DateTime")
                        {
                            filaDatos[k] = dr.GetDateTime(k).ToShortDateString();
                        }
                    }
                    actividades.Add(filaDatos);
                }//while dr.read
            }
            dictActividades.Add(nombreArchivo, actividades);
        }//for archivos

虽然这段代码非常简短并且使用了我能想到的最少的数据结构,但打印非常困难,因为密钥是员工的用户名而不是日期,代码应该打印每个员工的每个活动以上面发布的格式为例的日期

2 个答案:

答案 0 :(得分:2)

如果您没有在语义上组织它并在模型中包含逻辑,那么对这些数据执行逻辑将非常不直观。考虑引用:

  

&#34;智能数据结构和哑代码比其他方式更好。&#34;
   - Eric Raymond,大教堂和市集

您描述的结构包含您需要的所有信息:

  

第一天:
   员工#1:
     - 任务一      - 任务b
    -Task c

所以你从一个Task对象开始:

class Task
{
    // fields which describe a Task
}

(您可能希望将其命名为略有不同,以避免与内置Task类型混淆。可能JobJobTask或类似内容?)

员工拥有一系列任务:

class Employee
{
    public IList<Task> Tasks { get; set; }
}

一天有一系列员工:

class Day
{
    public IList<Employee> Employees { get; set; }
}

(如果这个域超出了这一个操作范围,那么你甚至可能会对事物的命名有所不同。从技术上讲,这些是&#34;员工&#34;就像他们是&#34; EmployeeTaskLogs&#34;等等。域名的大小和复杂性将指导任何此类命名。但绝对要考虑最合理的名称,这是本练习的重点。)

然后,您的顶级消费代码将只有一个天的集合:

var days = new List<Day>();

您可以通过创建自定义集合类型来进一步优化业务逻辑。例如,如果您想利用天词典:

class DayDictionary<T> : IDictionary<T> where T : Day
{
    // implement IDictionary<T> here
}

在这里,您可以包含逻辑,例如确保任何给定集合恰好具有5天对象。

一旦你定义了你的模型结构,使用它们就变得微不足道了,它们的语义变得明显。

答案 1 :(得分:2)

我建议像这样的简单类

class EmployeeActivity
{
    public string Employee { get; set; }
    public DateTime Date { get; set; }
    public string Activity { get; set; }
}

没有特殊的数据结构 - 仅List<EmployeeActivity>。填充后,您可以使用LINQ执行所需的排序/分组。

想象一下,而不是你字典,你填写我的建议

var empoyeeActivies = new List<EmployeeActivity>();
// Iterate excel files like in your code and populate the list

现在您可以使用

将其转换为示例中显示的方式
var result = employeeActivities
    .GroupBy(a => a.Date, (date, dateActivities) => new
    {
        Date = date,
        DateActivities = dateActivities
            .GroupBy(a => a.EmployeeName, (employeeName, employeeActivities) => new
            {
                EmployeeName = employeeName,
                Activities = empoyeeActivities.OrderBy(a => a.Activity)
            })
            .OrderBy(a => a.EmployeeName)
    })       
    .OrderBy(a => a.Date);