【问题标题】:C# dictionary vs 2D arrayC# 字典 vs 二维数组
【发布时间】: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 数组的完美用例。再说一次,这个问题是基于意见的,可能很快就会结束(Stackoverflow 对意见过敏)
  • 字典是二进制散列,项目数为 Log(N)。如果您查找 30 个字典,则查找将是 30/2*(log(N/30) 并且您必须与 Log(N) 进行比较才能看到差异。直接列表中的查找是 N/2,这是平均值找到该项目之前的测试量。

标签: c# arrays performance dictionary memory


【解决方案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 易于使用,它允许以一致的格式将数据汇集到其中,嵌入其他允许进行排序、搜索等的属性。如果将来数据负载会增加,请继续创建模型。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2015-11-28
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2016-12-10
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多