我想读取一个以制表符分隔的文件,其中第一行是标题
此实现的目标是在尝试进行以下索引工作时,不浪费内存和时间为每一行创建字典:line[column_name]
这是我的Python实现:
def readf(filename):
for i, line in enumerate(open(filename)):
cols = line.strip().split('t')
if i==0:
class Line:
_header = {col: i for i, col in enumerate(cols)}
def __init__(self, data):
self.data = data
def __getitem__(self, key):
return self.data[self._header[key]]
else:
yield Line(cols)
if __name__ == "__main__":
ll = []
for line in readf("hello.tsv"):
ll.append(line["col1"])
这能在C#中以类似的方式实现吗
我是C#的新手,从我搜索到的内容来看,它不支持在函数中定义类
C#中的闭包在网络上似乎没有有用的资源
感谢
编辑:前面的实现需要3.3秒,下面的实现对于一个1GB的文件需要4秒,其中大约有1M行
from itertools import izip
def readf(filename):
header = []
for i, line in enumerate(open(filename)):
cols = line.strip().split('t')
if i==0:
header = list(cols)
else:
yield {header:cols for header,cols in izip(header, cols)}
if __name__ == "__main__":
ll = []
for line in readf("hello.tsv"):
ll.append(line["col1"])
根据讨论,有几种方法可以实现这一点:
词典列表:
List<Dictionary<string, string>> aLines = new List<Dictionary<string, string>>();
var aFile = File.ReadAllLines(filename);
var aColumns = aFile.First().Split('t');
aFile.Skip(1).ToList().ForEach(line =>
{
var aSplitLine = line.Split('t');
Dictionary<string, string> aDictionary = new Dictionary<string, string>();
for (int i = 0; i < aSplitLine.Length; i++)
{
aDictionary.Add(aColumns[i], aSplitLine[i]);
}
aLines.Add(aDictionary);
});
int row = 0;
string fieldValueExample = aLines[row]["field_Value"];
或者通过创建顺序查找:
var aFile = File.ReadAllLines(filename);
int anIndex = 0;
var aColumns = aFile.First().Split('t').ToDictionary(field => field,field => anIndex++);
var aFileData = aFile.Skip(1).Select(line => line.Split('t')).ToList();
var row = 0;
string fieldValueExample = aFileData[row][aColumns["field_Value"]];
我还没有看过编译后的输出,但我认为第二个输出在技术上更快,但由于导入过程中执行的操作较少,因此以可读性为代价。不过,在读取字段值时,权衡可能是您正在查看两个索引以得出字段值。
最后,我不愿意像这样预先优化。做你可读和可维护的事情,以及谁将首先帮助你,看看这是否能完成任务。在大多数环境中,没有人会注意到运行时间延长了几秒钟。
或者。。或者,如果您试图获得与.Net的互操作性(而不是端口到C#的要求),您可以始终使用Iron Python。
http://ironpython.net/