想請問各位大大,有一個一百多萬筆的股票資料
資料分別有:交易日期,股票ID,股票名字,卷商ID,卷商名字,價錢,買數,賣數
例:20131210,7894,台積電,551E,第一新竹,205.5,2,0
20131210,7894,台積電,5214K,第一台北,206.5,3,2
20131210,7893,洋華,524K,元大台北,100.5,3,0
20131210,7893,洋華,524K1,元大高雄,99.5,1,5
請問有甚麼方法能夠存取並快速取用這些資料呢?
例:快速取的所有股票ID:台積電的所有資料
測了一下 100 萬筆資料LINQ + Where
可以在 1 秒內處理完
所以改用 1000 萬筆測試
class Program
{
static void Main(string[] args)
{
using var fs = new FileStream(@"test.csv", FileMode.OpenOrCreate);
using var sw = new StreamWriter(fs);
sw.WriteLine("交易日期,股票ID,股票名字,卷商ID,卷商名字,價錢,買數,賣數");
for (var i = 0; i < 10000000; i++)
sw.WriteLine(
$"20131210,7894,台積電{i / 5},551E,第一新竹,205.5,2,0");
}
}
class Program
{
static void Main(string[] args)
{
//耗時: 1毫秒
var list = File.ReadLines(@"test.csv")
.Skip(1)
.Select(it => it.Split(','));
//耗時: 5秒
var data = list.Where(it => it[2] == "台積電10500")
.ToList();
//耗時: 5秒
var data2 = list.Where(it => it[2] == "台積電25000")
.ToList();
}
}
class Program
{
static void Main(string[] args)
{
//耗時: 29秒
var dict = File.ReadLines(@"test.csv")
.Skip(1)
.Select(it => it.Split(','))
.GroupBy(it => it[2])
.ToDictionary(it => it.Key);
//耗時: 1毫秒
var data = dict["台積電10500"].ToList();
//耗時: 1毫秒
var data2 = dict["台積電25000"].ToList();
}
}
class Program
{
static void Main(string[] args)
{
//耗時: 27秒
var lookup = File.ReadLines(@"test.csv")
.Skip(1)
.Select(it => it.Split(','))
.ToLookup(it => it[2]);
//耗時: 1毫秒
var data = lookup["台積電10500"].ToList();
//耗時: 1毫秒
var data2 = lookup["台積電25000"].ToList();
}
}
100 萬筆資料使用一般的 Where 就足夠應付
假設資料到達 1000 萬級數
則要看需不需要每次查詢都重新載入資料
如果需要的話還是使用 Where 最合適
雖然每次查詢都要 5 秒
但比起製作 Dictionary 的時間還是少很多
如果資料只需載入一次
使用 Dictionary 或 Lookup 更為合適
雖然載入時間長,但後續查詢都可以在 1 毫秒內完成
Dictionary 因為 Key 只能有一個
所以需要多做一次 GroupBy
Lookup 則可以一個步驟就達成上面兩個步驟的效果
會快一點點,不過沒有差多少
選一個喜歡的就可以
如果查詢條件不固定
就不建議使用 Dictionary 或 Lookup
因為字典只能擁有一個 Key 值
用 File.ReadAllLines() 把 CSV讀進string[]裡
再用 Split用逗號把每個欄位資料取出
using System;
using System.IO;
namespace testtime
{
class Program
{
static void Main(string[] args)
{
string[] alist = File.ReadAllLines("test.csv");
foreach(string l in alist)
{
string[] cells = l.Split(new char[',']);
if(cells[2].Trim() == "台積電")
{
Console.WriteLine(cells); // 你自己懂得後續怎麼做了
}
}
}
}
}
還不夠快嗎?可以考慮再做class來parseCSV,但這對於你現在的狀況而言,有點遠
大哥你好:
我現在是把資料ReadLine進LIST,再從裡面FOREACH或LINQ撈要的資料做計算然後輸出datagriview。
但如果要撈全部的股票的話會跑很慢,所以想說有沒有可以快速取資料的方式來取代FOREACH或LINQ的做法,或是把範圍縮小再FOREACH或LINQ來節省時間。by菜鳥助工
qwe891107
宣告一個CLASS,才好用LINQ
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
namespace testtime
{
class Program
{
static void Main(string[] args)
{
string[] alist = File.ReadAllLines("test,csv");
var CSV = new List<CSVLine>();
foreach (string l in alist)
CSV.Add(new CSVLine(l));
//印出所有台積電的資料
foreach (var l in CSV.Where(p => p.coName == "台積電"))
{
Console.WriteLine(l.coID, l.coName, l.data[0]); // ..
}
}
}
class CSVLine
{
public DateTime dt { get; set; }
public string coID { get; set; }
public string coName { get; set; }
public List<string> data { get; set; }
public CSVLine(string line)
{
data=new List<string>();
string[] detail = line.Split(new char[',']);
dt = Convert.ToDateTime(detail[0]);
coID = detail[1];
coName = detail[2];
data.AddRange(detail.Skip(3)); // 跳過前三個元素不要
}
}
}
已經有宣告CLASS 並用LIST< CLASS > 存取了
改這樣試試看,先宣告成IEnumerable,最後條件查完在ToList出來
private static void Main(string[] args)
{
// 取得資料
IEnumerable<Stock> alist = File.ReadLines("stockTest.csv",System.Text.Encoding.GetEncoding("Big5"))
.GroupBy(x => x.Split(','))
.Select(s => new Stock()
{
Date = DateTime.ParseExact(s.Key[0], "yyyyMMdd", null),
StockId = s.Key[1],
StockName = s.Key[2]
});
var a = alist.Where(x => x.StockName == "台積電").ToList();
}
public class Stock
{
public DateTime Date { get; set; }
public string StockId { get; set; }
public string StockName { get; set; }
}