1

我的目标:我要总结一个 1 GB 的 csv 文件。假设该文件具有“字段”/列 AM。我想将某些字段小计到另一个字段上,比如 A。我想要的结果是字段 A 中的每个值以及其他三个字段的小计 - 比如 B、G 和 L。

问题:我正在尝试使用 LINQ 查询来处理此问题,但会引发 Out of Memory 异常。

这是我的查询:

Dim summarizedRecs = From line In System.IO.File.ReadLines(filepath)
       Skip 1
       Let e = New aRecord(line)
       Group e
       By e.A
       Into g = Group
       Select summarizedR = New With {
           A,
           .TotalB = g.Sum(Function(x) x.B),
           .TotalG = g.Sum(Function(x) x.G),
           .TotalL = g.Sum(Function(x) x.L)}
       Order By summarizedR.A

aRecord是一个简单的类,它的构造函数接受一行文本并将该行解析为适当的字段。这很好用。

这种方法适用于 ~ 100 MB 的较小文件。对于 100 MB 文件和 1 GB 文件,应用程序使用的内存会随着运行时间的增加而增加。

我怀疑 LINQ 组不是我想要的,但我不确定另一种 LINQ 方法。有吗?

我认为 LINQ 将我所有的 e 实例保留在组中。最后,我不需要 e 组。在将每个 e 的字段添加到适当的组之后,可以处置该 e。我只想要来自 e 组的结果小计。

我也一起跳过了 LINQ,并使用 Dictionary(Of T1, T2) 成功实现了这一点。这样做,我阅读了每一行文本,创建了一个 aRecord 的实例并将其总数应用于字典中适当的键值对。在这种方法中,只有一个 aRecord 实例。这在内存方面是有效的——消耗的内存趋于平稳并保持相对较低。

因此 Dictionary 方法适用于 1 GB 文件。有没有 LINQ 替代方案?

4

1 回答 1

1

坚持你的解决方案没有错Dictionary,但如果你想使用 LINQ,你可以使用Aggregate

Dim summarizedRecs = File.ReadLines(filepath) _
                         .Skip(1) _
                         .Select(Function(line) New aRecord(line))
                         .Aggregate(New Hashtable(), Function(acc, cur) 
                                                        acc(cur.A) += cur : Return acc
                                                     End Function)

以及为方便起见实现 -operator的aRecord类:+

Private Class aRecord
    Public Property A As String
    Public Property B As Integer
    Public Property G As Integer
    Public Property L As Integer
    Public Shared Operator +(a As aRecord, b As aRecord) As aRecord
        If a is Nothing Then Return b

        Return New aRecord() With { _
            .A = a.A, _
            .B = a.B + b.B, _
            .G = a.G + b.G, _
            .L = a.L + b.L _
        }
    End Operator
End Class

我在Hashtable这里使用 a 而不是Dictionary因为 a如果找不到特定键则Hashtable返回,并在-operator 中滥用这一事实(只是为了节省一些代码行)。Nothing+

我也不知道你的aRecord类做了什么,但在这个例子中,我滥用它来存储累积的字段B,GL(同样,为了保存一些代码行)。

但是,在现实世界的应用程序中,我可能会使用简单的For Each循环而不是试图变得聪明。

于 2013-09-18T13:47:59.030 回答