2015-12-07 1 views
0

Я хотел бы прочитать файл с разделителями, в котором первая строка является заголовком.
Целью данной реализации является не тратить память и время, чтобы создать словарь для каждой строки при попытке иметь эту индексацию работу: line[column_name]
Это моя реализация Python:Реализовать динамический класс с закрытием в C#, как в этом коде 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#, похоже, не имеет полезных ресурсов в Интернете.
Благодаря

Edit: предыдущей реализации занимает 3.3s, следующих один принимает 4s для файла 1Гб около 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"]) 
+0

Это, как представляется, проблема X-Y, чтение файла с разделителями табуляции в C# не должны «тратить» память. Что вы пытаетесь сделать с данными, прочитать все это в памяти и затем проиндексировать? –

+0

сделать Hashset определенной группы столбцов – titus

+0

Есть ли причина, по которой он должен выводить класс? Или будет работать простой выход пары «ключ-значение»? – MutantNinjaCodeMonkey

ответ

2

За обсуждение, несколько способов для достижения этой цели:

Список словарей:

 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/

+0

Я сделал аналогичную реализацию и занимает около 5 секунд, хороший эог. Благодаря! – titus

+0

хотя C# развил блогпост в основном по-прежнему верен 9 лет спустя http://lukeplant.me.uk/blog/posts/why-learning-haskell-python-makes-you-a-worse-programmer/ – titus

+0

Python и C# разделяют много общего в своей философии дизайна. В самых последних версиях синтаксиса C# существует гораздо более функциональное программирование. Это, несомненно, связано с влиянием других языков, таких как Python, Ruby и Haskell. «Объектно-ориентированные» концепции объектов Python, за некоторыми исключениями, фактически портят на C# довольно хорошо. – MutantNinjaCodeMonkey