[英]C# Datatype for large sorted collection with position?
我試圖比較SQL查詢中的兩個大數據集。 現在,SQL查詢是在外部完成的,每個數據集的結果都保存在自己的csv文件中。 我的小C#控制台應用程序加載兩個text / csv文件,並將它們與差異進行比較,並將差異保存到文本文件中。
它是一個非常簡單的應用程序,它只是將第一個文件中的所有數據加載到arraylist中,並在arraylist上執行.compare(),因為每行都是從第二個csv文件中讀取的。 然后保存不匹配的記錄。
該應用程序有效,但我想提高性能。 我想我可以大大提高性能,如果我可以利用兩個文件都已排序的事實,但我不知道C#中保持順序的數據類型,並允許我選擇一個特定的位置。 這是一個基本數組,但我不知道每個列表中有多少項。 我可以有超過一百萬條記錄。 是否有可用的數據類型我應該查看?
如果兩個CSV文件中的數據已經排序並且具有相同數量的記錄,則可以完全跳過數據結構並進行就地分析。
StreamReader one = new StreamReader("C:\file1.csv");
StreamReader two = new StreamReader("C:\file2.csv");
String lineOne;
String lineTwo;
StreamWriter differences = new StreamWriter("Output.csv");
while (!one.EndOfStream)
{
lineOne = one.ReadLine();
lineTwo = two.ReadLine();
// do your comparison.
bool areDifferent = true;
if (areDifferent)
differences.WriteLine(lineOne + lineTwo);
}
one.Close();
two.Close();
differences.Close();
System.Collections.Specialized.StringCollection允許您添加一系列值,並使用.IndexOf(字符串)方法,允許您檢索該項的索引。
話雖這么說,你可能只是從文件流加載幾個byte []並進行字節比較......甚至不用擔心將這些東西加載到像StringCollection或string []這樣的正式數據結構中; 如果您所做的只是檢查差異,並且您想要速度,我會想到字節差異就在它的位置。
這是David Sokol的代碼改編,用於處理不同數量的行,輸出一個文件而不是另一個文件中的行:
StreamReader one = new StreamReader("C:\file1.csv");
StreamReader two = new StreamReader("C:\file2.csv");
String lineOne;
String lineTwo;
StreamWriter differences = new StreamWriter("Output.csv");
lineOne = one.ReadLine();
lineTwo = two.ReadLine();
while (!one.EndOfStream || !two.EndOfStream)
{
if(lineOne == lineTwo)
{
// lines match, read next line from each and continue
lineOne = one.ReadLine();
lineTwo = two.ReadLine();
continue;
}
if(two.EndOfStream || lineOne < lineTwo)
{
differences.WriteLine(lineOne);
lineOne = one.ReadLine();
}
if(one.EndOfStream || lineTwo < lineOne)
{
differences.WriteLine(lineTwo);
lineTwo = two.ReadLine();
}
}
關於代碼寫在我頭頂的標准警告適用 - 你可能需要特殊情況下一行中沒有行,而另一行仍然有行,但我認為這種基本方法應該做你想要的。
那么,有幾種方法可行。 您可以編寫自己的數據結構來執行此操作。 或者您可以嘗試使用SortedList。 您還可以在代碼中返回DataSet,然后在表上使用.Select()。 當然,您必須在兩個表上執行此操作。
您可以輕松使用SortedList進行快速查找。 如果要加載的數據已經排序,則對SortedList的插入不應該很慢。
如果您只想查看FileA中的所有行是否都包含在FileB中,您可以讀取它並僅比較循環內的流。
文件1 Entry1 Entry2 Entry3
文件2 Entry1 Entry3
您可以通過兩個計數器循環查找遺漏,逐行瀏覽每個文件,看看是否得到了您需要的東西。
也許我誤解了,但ArrayList將按照添加它們的順序維護其元素。 這意味着您只能在一次通過中比較兩個ArrayLists - 只需根據比較結果遞增兩個掃描索引。
我有一個問題是你考慮過“外包”你的比較。 有很多很好的差異工具,你可以呼吁。 如果沒有一個允許你指定兩個文件並且只獲得差異,我會感到驚訝。 只是一個想法。
我認為每個人都有這么多不同答案的原因是你沒有完全指出你的問題得到回答。 首先,它取決於您想要跟蹤的差異。 您是否希望在WinDiff中輸出差異,其中第一個文件是“原始”,第二個文件是“已修改”,因此您可以將更改列為INSERT,UPDATE或DELETE? 您是否有一個主鍵,允許您將兩行匹配為同一記錄的不同版本(當主鍵以外的字段不同時)? 或者這是某種和解,你只是希望你的差異輸出說“記錄在文件1而不是文件2”?
我認為這些問題的答案將幫助每個人為您的問題提供合適的答案。
如果你有兩個文件,每個文件都是你的帖子中提到的一百萬行,你可能會耗費大量內存。 某些性能問題可能是您正在從磁盤交換。 如果您只是將文件A的第1行與文件B,第2行文件A - >第2行文件B等的第一行進行比較,我建議使用一種不會在內存中存儲太多的技術。 你可以讀取兩個文件流的注銷,就像之前發布的評論者一樣,並在你找到它們時“實時”寫出你的結果。 這不會在內存中明確存儲任何內容。 你也可以將每個文件的塊轉儲到內存中,比如一次說一千行,就像List一樣。 這可以很好地調整,以滿足您的需求。
要解決問題#1,我建議您考慮創建每行的哈希值。 這樣,您可以使用字典快速輕松地比較哈希。
要解決問題#2,一個快速而骯臟的解決方案是使用IDictionary。 使用itemId作為第一個字符串類型,將行的其余部分用作第二個字符串類型。 然后,您可以快速查找itemId是否存在並比較這些行。 這當然假設.Net 2.0+
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.