2015-02-11 98 views
0

我有這樣的代碼:如何使計算兩行之間在特定的列在列表中

using System; 
using System.Collections.Generic; 
using System.Linq; 
using System.IO; 

namespace CsvDemo 
{ 
class Program 
{ 
    static void Main(string[] args) 
    { 
     List<DailyValues> values = File.ReadAllLines("C:\\Users\\Josh\\Sample.csv") 
             .Skip(1) 
             .Select(v => DailyValues.FromCsv(v)) 
             .ToList(); 
    } 
} 

class DailyValues 
{ 
    DateTime Date; 
    decimal Open; 
    decimal High; 
    decimal Low; 
    decimal Close; 
    decimal Volume; 
    decimal AdjClose; 

    public static DailyValues FromCsv(string csvLine) 
    { 
     string[] values = csvLine.Split(','); 
     DailyValues dailyValues = new DailyValues(); 
     dailyValues.Date = Convert.ToDateTime(values[0]); 
     dailyValues.Open = Convert.ToDecimal(values[1]); 
     dailyValues.High = Convert.ToDecimal(values[2]); 
     dailyValues.Low = Convert.ToDecimal(values[3]); 
     dailyValues.Close = Convert.ToDecimal(values[4]); 
     dailyValues.Volume = Convert.ToDecimal(values[5]); 
     dailyValues.AdjClose = Convert.ToDecimal(values[6]); 
     return dailyValues; 
     } 
    } 
} 
  1. File.ReadAllLines讀取來自CSV所有行文件轉換成字符串數組。
  2. .Skip(1)跳過標題行。
  3. .Select(v => DailyValues.FromCsv(v))使用Linq選擇每一行並使用FromCsv方法創建一個新的DailyValues實例。這會創建一個System.Collections.Generic.IEnumerable<CsvDemo.DailyValues>類型。
  4. 最後,.ToList()將IEnumerable轉換爲List來匹配您想要的類型。

但我的問題是如何在兩個單元之間進行計算。例如,我想在第3列中添加第2和第3行,並將結果顯示在最後一列中。

+0

從你的解釋看來,你只需要迭代t通過'Main'中的'values'並手動進行計算。這是重複添加還是僅僅一次?根據這一點,這種做法會有所不同。 – Andrew 2015-02-11 13:36:24

+0

我有一個csv文件,我想在特定列中的兩行之間進行添加,並且我想要在最後一列中顯示結果。任何想法? – Gio7 2015-02-11 13:38:48

+1

是的,你說過,給我們一個例子,使用數據,輸入和所需的輸出 – Jamiec 2015-02-11 13:39:18

回答

1

看起來(儘管我依靠這裏的一些想法)你試圖在列表的每個記錄上都有一個運行平衡字段。你已經有代碼項目您的原始CSV數據爲對象的列表:

List<DailyValues> values = File.ReadAllLines("C:\\Users\\Josh\\Sample.csv") 
            .Skip(1) 
            .Select(v => DailyValues.FromCsv(v)) 
            .ToList() 

你需要做的,從有再次投射到另一個列表中,這樣做計算,你去什麼。顯然這個計算對第一行不能做任何事情,因爲它需要一個先前的值,所以在這種情況下,你將它設置爲零。

class DailyValuesWithTotal : DailyValues 
{ 
    decimal TotalHigh 
} 
var projectedValues = values.Select((v,i) => new DailyValuesWithTotal(){ 
    Date = v.Date, 
    Open = v.Open, 
    High = v.High, 
    Low = v.Low, 
    Volume = v.Volume, 
    AdjClose = v.AdjClose,  
    TotalHigh = (i == 0) ? 0.0 : values[i-1].TotalHigh + v.High 
}) 

上面的示例保持一個運行總計的High字段的在稱爲TotalHigh新字段。

+0

是的這樣的事情。我想總結當前高與前一個高,結果必須顯示在當前結果的行 – Gio7 2015-02-11 14:11:31

+0

@ user3616435 - 好的,請參閱更新 – Jamiec 2015-02-11 14:17:20

0

如果我正確理解你的問題,你想總結當前行和下一行的值到當前行的最後一列。

如果這是正確的,您可以在讀取文件中的所有數據後用for循環執行此操作。只需在你的課堂中添加一個屬性,即可填寫該循環。

+0

是的,這正是我想要做的!你能幫我一下房產嗎? – Gio7 2015-02-11 13:59:09

0

首先,我建議使用FileHelpers或另一個CSV解析庫,因爲它會使您的代碼更容易(特別是錯誤處理,處理引號等)。

(我將在我的答案使用這個庫,但你不必)

一個新的屬性添加到您的類存儲計算的值:

[IgnoreFirst(1)] 
[DelimitedRecord(",")] 
class DailyValues 
{ 
    [FieldConverter(ConverterKind.Date, "yyyy-MM-dd")] 
    public DateTime Date; 
    public decimal Open; 
    public decimal High; 
    public decimal Low; 
    public decimal Close; 
    public decimal Volume; 
    public decimal AdjClose; 
    [FieldNotInFile] 
    public decimal SomethingCalculated; 
} 

然後,只需循環通過你的元素,並使用一個臨時變量來跟蹤你感興趣的前一個元素的值,以便你可以進行計算:

var engine = new FileHelperEngine(typeof(DailyValues)); 
var res = engine.ReadFile(@"your:\path") as DailyValues[]; 

decimal? prev = null; 
foreach(var value in res) 
{ 
    if(prev.HasValue) 
     // or whatever columns you want to use 
     value.SomethingCalculated = value.High + prev.Value; 
    prev = value.Open; 
} 
相關問題