【问题标题】:Reading a CSV file and extracting specific data [closed]读取 CSV 文件并提取特定数据 [关闭]
【发布时间】:2015-06-05 15:10:35
【问题描述】:

所以我有一个 .CSV 文件,其中可能包含数百万甚至数十亿行数据。数据格式如下:

1,,5,6,7,82,4,6
1,4,4,5,6,33,4,
2,6,3,,6,32,6,7
,,,2,5,45,,6
,4,5,6,,33,5,6

我想要实现的是:让我们假设每一行数据都是一个“事件”。让我们这样称呼它。现在假设用户说,显示第 6 个值为 33 的所有事件。您可以在上面看到第 6 个数据元素是一个 2 位数字,用户可以说显示第 6 个数据元素为 33 的所有事件,并且输出将是:

1,4,4,5,6,33,4,
,4,5,6,,33,5,6

此外,如您所见。数据可能有缺失数据的空白或孔洞。我不需要帮助来阅读 .CSV 文件或任何东西。我只是想不通我将如何访问第 6 个数据元素。另外,我希望这个输出可能以某种集合的形式表示。我是 C# 新手,所以我对内置类知之甚少。任何帮助将不胜感激!

【问题讨论】:

  • 听起来你可能需要开源库 LinqToCsv?

标签: c# wpf csv


【解决方案1】:

我建议不要使用术语“事件”来更习惯地将此数据结构称为“行和列”,并使用 C# Split() 函数创建二维数组(string[,] 或 int[,]),其中每个元素可以通过其行/列索引方便地访问,并将任何业务逻辑应用于这些元素。

CSV 文件阅读器的可能实现(按行,每行存储在 List<string> listRows 中)如下所示(回复:Reading CSV file and storing values into an array)

using System.IO;
static void Main(string[] args)
{
    var reader = new StreamReader(File.OpenRead(@"C:\YouFile.csv"));
    List<string> listRows= new List<string>();
    while (!reader.EndOfStream)
    {
        listRows.Add(reader.ReadLine());
    }
}

然后将Split(',')函数应用于每一行(存储在listRows中)以组成一个二维数组string[,]并使用int.TryParse()方法将其转换为类型int(可选,根据需要)。

或者,这可以通过使用 LINQ 库来实现,但不建议这样做,因为不必要地扩展了技术表面积,并且可能会降低性能(LINQ 解决方案预计比建议的直接处理要慢)。

希望这会有所帮助。

【讨论】:

    【解决方案2】:

    使用 Linq 很容易实现。我从 LinqPad 发布样本并提供输出。只需将 33 替换为参数即可:

    void Main()
    {
    string csvFile = @"C:\Temp\TestData.csv";
        string[] lines = File.ReadAllLines(csvFile);
    
        var values = lines.Select(s => new { myRow = s.Split(',')});
    //and here is your collection representing results  
       List<string[]> results = new List<string[]>();
    
        foreach (var value in values)
        {
           if(value.Values.Contains("33")){
            results.Add(value.myRow);
           }
        }
    
        results.Dump();
    }
    

    输出:

    或者,如果您愿意,您可以通过这样做一次性完成所有操作

     string csvFile = @"C:\Temp\TestData.csv";
     string[] lines = File.ReadAllLines(csvFile);
    
      var values = lines.Select(s => 
        new {Position =Array.FindIndex(s.Split(','),a=>a.Contains("33"))+1
             ,myRow = s.Split(',')
            });
    

    因此最终产品将同时具有 - 您的搜索位置 (33) 和项目的完整字符串 []。

    【讨论】:

      【解决方案3】:

      创建一个类EventEntity。在此类中,使用初始化列表的构造函数创建一个List&lt;int&gt;。这是一个类示例:

          public class EventEntity
          {
              public EventEntity()
              {
                  EventList = new List<int>();
              }
      
              public List<int> EventList { get; set; }
          }
      

      从那里循环遍历每一行数据。示例:

      public class EventEntityRepo
      {
          public EventEntity GetEventEntityByCsvDataRow(String[] csvRow)
          {
              EventEntity events = new EventEntity();
      
              foreach (String csvCell in csvRow)
              {
                  int eventId = -1;
      
                  if(csvCell != null && csvCell != String.Empty)
                  {
                      try
                      {
                          eventId = Convert.ToInt32(csvCell.Trim());
                      }
                      catch (Exception ex)
                      {
                          //failed to parse int
                      }
                  }
      
                  events.EventList.Add(eventId); //if an empty item, insert -1
              }
      
              return events;
          }
      }
      

      然后您可以随时参考这些项目。

      eventEntityList = GetEventEntityByCsvDataRow(csvDataRow);
      eventEntitySixthElement = eventEntityList[5];
      

      【讨论】:

        【解决方案4】:

        所以您的问题是如何访问第 6 个数据元素。如果你有正确的数据结构来代表你的 csv,这并不难。

        基本上,这个抽象术语的 csv 文档可以描述为IEnumerable&lt;IEnumerable&lt;String&gt;&gt;,或者,也许是IEnumerable&lt;IEnumerable&lt;int?&gt;&gt;。实现 csv 解析逻辑后,您将通过执行访问第 6 个元素:

        var csvRepresenation = ParseCsv(@"D:/file.csv");
        var element = csvRepresentation.ElementAt(6);
        if (element == "6")
        {
            // do smth
        }
        

        通过这种方法,您还可以在其上执行 Linq 语句。 现在的问题是你将如何实现ParseCsv():

        public IEnumerable<IEnumerable<String>> ParseCsv(string path)
        {
            return File.ReadAllLines(path).Select(row => row.Split(','));
        }
        

        【讨论】:

          猜你喜欢
          • 2019-10-14
          • 2022-12-24
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2020-08-01
          • 1970-01-01
          相关资源
          最近更新 更多