web-dev-qa-db-ja.com

オブジェクトのリストへのCSVの読み取り

さまざまなデータ(日時、10進数)のリストを含むCSVファイルがあります。 CSVのサンプル行:

Date,Open,High,Low,Close,Volume,Adj Close  //I need to skip this first line as well
2012-11-01,77.60,78.12,77.37,78.05,186200,78.05

各行を読みたいオブジェクトのリストを作成しました。オブジェクトのコンストラクタは以下のとおりです。各CSV行の各フィールドが使用され、ここに割り当てられます。

    public DailyValues(DateTime date, decimal open, decimal high, decimal low,
        decimal close, decimal volume, decimal adjClose)
        : this()
    {
        Date = date;
        Open = open;
        High = high;
        Low = low;
        Close = close;
        Volume = volume;
        AdjClose = adjClose;
    }

    List<DailyValues> values = new List<DailyValues>();

CSVの各行をリストvaluesに読み込み、各属性(日付、オープン、高など)を適切に割り当てる簡単な方法はありますか?

26
user3066571

なぜこれらを明示的に解析しないのですか?プロパティの数は限られているため、それほど難しくありません。多くの引数を必要とするコンストラクターを使用する代わりに、新しいDailyValuesインスタンスを返す型として返す静的メソッドを使用しました。これは_DateTime.FromBinary_などに似ています。

_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;
        }
    }
}
_

もちろん、デフォルトのコンストラクタを追加することはできますが、解析が失敗した場合に例外処理を追加することもできます(そのためにTryParseを使用することもできます)。

  • _File.ReadAllLines_は、CSVファイルからすべての行を文字列配列に読み取ります。
  • .Skip(1)はヘッダー行をスキップします。
  • .Select(v => DailyValues.FromCsv(v))はLinqを使用して各行を選択し、DailyValuesメソッドを使用して新しいFromCsvインスタンスを作成します。これにより、_System.Collections.Generic.IEnumerable<CsvDemo.DailyValues>_型が作成されます。
  • 最後に、.ToList()IEnumerableListに変換して、必要なタイプに一致させます。

Linqを使用する代わりに、foreachループを使用して各DailyValuesインスタンスをリストに追加することもできます。

71
grovesNL