C# 字典 vs 二维数组

Posted

技术标签:

【中文标题】C# 字典 vs 二维数组【英文标题】:C# dictionary vs 2D array 【发布时间】:2021-12-02 01:00:37 【问题描述】:

我有一个 5000 行 * 30 列的 Excel 工作表,我想将它们读入 C# 程序,然后通过查找行标题和列标题定期访问这些值。该程序将在普通笔记本电脑(16GB 内存)上运行。我应该使用字典词典来存储这些数据吗?如果是这样,是否更建议创建一个包含 5000 个较小字典的字典,每个字典具有 30 个键值对(即,行标题将是“外部”字典的键,列标题将是“内部”字典的键字典)还是 30 个字典,每个字典有 5000 个键值对?或者我应该创建一个二维数组,并将行标题和行索引对以及列标题和列索引对存储在 2 个较小的字典中?还是我需要担心这么多数据的内存/性能问题?

谢谢。

【问题讨论】:

您应该创建一个 Model 类,其中 Properties 将是您的 30 列,其值将是 5000 行中的值。因此,您将只有一个 List<Model>,其中包含 5000 个模型项。 5000 行对于现代计算机来说没什么,即使行很大。 如果您在 Excel 电子表格中对数据进行建模(不包括合并单元格或其他 非矩形 功能),并且您将通过行和列访问它们数字,那么您就有了 2D 数组的完美用例。再说一次,这个问题是基于意见的,可能很快就会结束(*** 对意见过敏) 字典是二进制散列,项目数为 Log(N)。如果您查找 30 个字典,则查找将是 30/2*(log(N/30) 并且您必须与 Log(N) 进行比较才能看到差异。直接列表中的查找是 N/2,这是平均值找到该项目之前的测试量。 【参考方案1】:

解释注释的示例。

你有一些 N 列 N 行的表:

您可以创建一个代表一个对象(一个实体)的类:

public class Person


并用属性填充它,这对于每个实体(您的 30 列)都是相似的:

public class Person
 
    public string Name  get; set;
    public string Surname  get; set;
    public int Age  get; set;
    public string City  get; set;
    public string Gender  get; set;
    // and other of 30 columns

因此,表中的每一行代表某个人(在该示例中)。 5000 行 = 我们将有 5000 人。因为它们是相似的实体——我们可以将它们存储为集合或人员。我们可以使用(举个简单的例子):

Person[] - 人员数组; List<Person> - 人员列表;

让我们想象一下,如何从表中读取数据并从中创建一个人员列表。

public void ReadTable(Table myTable) // We have Table with Rows and Columns
 
    // Initializing our collection of Persons
    List<Person> persons = new List<Person>;

    // We need to read all 5000 rows, so iterating them
    for (int i = 1; i <= myTable.Rows.Count; i++) // myTable.Rows.Count = 5000
    
        // Creating a Person
        Person person = new Person(); 
        
        // Reading each cell value, accessing to it through RowIndex & ColumnIndex 

        // Row 1 Column 1 is Name 
        string name = myTable.Rows[i].Columns[1].Value.ToString(); // John
        // Row 1 Column 2 is Surname
        string surname = myTable.Rows[i].Columns[2].Value.ToString(); // Wick
        // Row 1 Column 3 is Age
        int age = int.Parse(myTable.Rows[i].Columns[3].Value); // 55  
        // Row 1 Column 4 is City
        string city = myTable.Rows[i].Columns[4].Value.ToString(); // New York 
        // Row 1 Column 5 is Gender
        string gender = myTable.Rows[i].Columns[5].Value.ToString(); // Male

        //Received from table values we add to a Person:
        person.Name = name;
        person.Surname = surname;
        person.Age = age;
        person.City = city;
        person.Gender = gender;
   
        // And finally adding Person to a collection (list) of Persons:
        persons.Add(person);

        // And same would happen with other 5000 rows                    
   

因此,阅读后您将拥有包含 5000 个项目的 persons 列表。您可以操作它们、编辑、添加新的和删除现有的 - 随便什么。

【讨论】:

【参考方案2】:

根据this,字典中一个元素的内存开销约为 20 字节。所以 5000 * 30 * 20 = 3000000 字节,或 3Mb,加上字典对象本身的几个 Kb。

由于这对于现代计算机来说微不足道,因此从内存的角度来看可能无关紧要。从性能的角度来看,这也可能无关紧要。

因此,如果您选择字典、锯齿状数组、二维数组或显式行对象,则应更多地从最容易使用的替代方案中确定。

如果所有单元格都具有相同的类型,则二维数组可能是最简单的选择。如果类型不同,为每列创建具有属性的 ModelRow 类可能最有用,这将有助于提供比简单的行/列更高级别的抽象。

【讨论】:

【参考方案3】:

正如@JonasH 所回答的那样,任何现代系统都可以处理 5000 行,为结构定义模型是继续前进的好解决方案。另一方面,您也可以将您的 Excel 数据加载到 DataTable 对象中。 DataTable 易于使用,它允许以一致的格式将数据汇集到其中,嵌入其他允许进行排序、搜索等的属性。如果将来数据负载会增加,请继续创建模型。

【讨论】:

以上是关于C# 字典 vs 二维数组的主要内容,如果未能解决你的问题,请参考以下文章

Swift 问题 - 数组列表中包含二维数组的字典

C#二维数组的介绍

C# CS结构中 2005 如何将二维数组转化成DataSet

C#从函数返回二维数组索引

C# 二维数组深入理解

C# Json如何转为二维数组或者datatable