高效的数据结构可容纳员工';的活动

本文关键字:活动 数据结构 可容纳 高效 | 更新日期: 2023-09-27 18:21:54

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

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

第1天至第5天:

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

员工#2:
-任务a
-任务b
-任务c

第2天:…


第7天至第11天:
。。。…

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

虽然我认为这些数据结构本身是高效的,但对于我的主要目标来说,它们并不太友好,因为我的主要目的是打印每个员工每天订购的数据,所以也许关键本身应该是日期。

概括一下:当前使用的数据结构:

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

每个员工excel文件中的所有行都存储在列表中。我真的不需要字典的功能,因为我可以把所有的东西都按顺序读回来。我可以在阅读员工的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

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

高效的数据结构可容纳员工';的活动

我建议使用一个类似的简单类

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

一个没有特殊数据结构-只有CCD_ 1。填充后,可以使用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);

如果不从语义上组织数据并将逻辑包含在模型中,那么对这些数据执行逻辑将是非常不直观的。考虑一下报价:

"智能数据结构和愚蠢的代码比其他方式工作得更好。"
-Eric Raymond,大教堂和集市

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

第一天:
员工#1:
-任务a
-任务b
-任务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; }
}

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

var days = new List<Day>();

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

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

例如,在这里,您可以包含一些逻辑,比如确保任何给定的集合都有精确的5天对象。

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