将列表写入CSV文件

6

我有一个名为NN的List of List of int,我想将它写入CSV文件,格式如下:

List<List<int>> NN = new List<List<int>>();

NN列表:
1,2,3,4,5,6
2,5,6,3,1,0
0,9,2,6,7,8

输出的CSV文件应该长这样:

1,2,0
2,5,9
3,6,2
4,3,6
5,1,7
6,0,8

如何最好地实现这一目标?

如果您有更好的表示方法而不是嵌套列表,我很乐意了解。

(目的是每个整数列表都是神经网络中上一层和下一层之间的权重。)


所以基本上 NN 是一列数据的列表,对吗? - Yacoub Massad
嵌套的 for 循环是一种简单的方法。 - Andrew Morton
2个回答

9
以下是方法:

这里是如何操作:

List<List<int>> NN = new List <List<int>>
{
    new List<int> {1,2,3,4,5,6},
    new List<int> {2,5,6,3,1,0},
    new List<int> {0,9,2,6,7,8}
};

//Get expected number of rows
var numberOfRows = NN[0].Count; 

var rows =
    Enumerable.Range(0, numberOfRows) //For each row
    .Select(row => NN.Select(list => list[row]).ToList()) //Get row data from all columns
    .ToList();

StringBuilder sb = new StringBuilder();

foreach (var row in rows)
{
    sb.AppendLine(string.Join(",", row));
}

var result = sb.ToString();

3
您想要实现的基本上是矩阵转置并将数据写入文件。
如何最有效地转置矩阵是一个复杂的问题,实际上取决于您的架构。
如果您不太关心为处理器(或加速器)进行超级优化,我建议使用简单的嵌套for循环,在中间存储表示中累积数据。
string[] lines = new string[NN[0].Count]; // assume all lines have equal length
for(int i = 0; i < NN.Count; ++i) {
  for(int j = 0; j < NN[i].Count; ++j) {
     lines[j] += NN[i][j] + ((i==NN.Count - 1) ? "" : ",");
  }
}
File.WriteAllLines("path.csv", lines);

作为第一个优化方案,我不建议使用列表嵌套列表,因为访问元素会非常耗费资源。 双维数组会更好地完成任务。

int[,] NN = new int[3,6] {{1, 2, 3, 4, 5, 6 }, {2, 5, 6, 3, 1, 0}, {0, 9, 2, 6, 7, 8}};

            string[] lines = new string[NN.GetLength(1)];
            for (int i = 0; i < NN.GetLength(0); ++i)
            {
                for (int j = 0; j < NN.GetLength(1); ++j)
                {
                    lines[j] += NN[i,j] + ((i == NN.GetLength(0) - 1) ? "" : ",");
                }
            }
            File.WriteAllLines("path.csv", lines); 

这是一个性能测试,针对500x500个元素(不包括写入文件):

enter image description here

要改进此解决方案,我首先会在内存中进行转置(而不写任何内容到文件或字符串中),然后执行join(,)并将其作为单个字节数组写入文件。

如果您想进一步优化,那么通常总有更多的空间可以利用 :)

例如,在x86上,根据您拥有的指令集,您可以阅读此文献。在启用了CUDA的设备上,您可以阅读这个

无论如何,一个好的解决方案总是涉及对齐内存、子块以及接近底层的编写代码(intrinsic或汇编语言)。


一个好的解决方案总是涉及到对齐内存、子块化以及近乎底层的编写代码(使用指令集或汇编语言)。而在C#中你无法得到这些,这使得本答案的前半部分有点不相关。 - Cody Gray
在C#中对齐内存是可能的(使用PInvoke VirtualAlloc),子块只是索引的问题,而且PInvoking子例程也是可能的(例如转置子块)。 - Regis Portalez

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接