2014-01-24 116 views
0

對不起,如果標題混亂,我不能確定我應該如何標籤,我試過。交叉索引引用

我正在寫一個程序做一些交叉索引搜索,該程序是使用Visual Studio 2010中

寫在C#我有3列的表格:CategoryTypeItem。該表是從excel電子表格讀入並存儲在某種數據結構中的(稍後將對此進行解釋)。以下是該表的簡短示例。

| CATEGORY | TYPE | ITEM | <<header row 
| categoryA | typeA | itemA | <<first entry 
| categoryA | typeB | N/A | 
| categoryA | typeC | itemB | 
| categoryA | typeD | N/A | 

我將讀取兩個用戶輸入字符串,並且我希望程序確定它們是否匹配。 [假設用戶輸入沒有錯字,我已經寫一個函數來處理這個和正常化兩個字符串]

確定兩個字符串是否匹配是這樣的邏輯:

1)如果字符串是一個CATEGORY,每TYPEITEM具有相同的CATEGORY是匹配。

2)如果字符串是TYPEITEM,在同一行中唯一的其他數據是匹配

下面是一些例子,串a和b是兩個輸入字符串和匹配是一個布爾值:

1) a = "categoryA", b = "typeA", match = true 
2) a = "categoryA", b = "itemB", match = true 
3) a = "typeC", b = "itemB", match = true 
4) a = "typeC", b = "itemA", match = false 
5) a = "itemA", b = "itemB", match = false 

如果這不夠清楚,我會給出更多的例子。

所以我的整體問題是:什麼是最適合的數據結構來存儲Excel電子表格中的數據,以及如何使用此數據結構進行搜索/比較匹配?

我雖然使用了Dictionary<string, string>,所以我可以在字典中搜索字符串a並獲取匹配字符串列表並進行比較,但是這樣我將會有一個巨大的字典和多個相同的密鑰,這是行不通的。

任何建議/幫助表示讚賞。

回答

2

我會考慮使用DataTableSystem.Data命名空間,它適合存儲在內存中的表格數據。什麼可能使它更具吸引力是你可以用SQL查詢它,如通過DataViewRowFilter屬性查詢。

一些僞代碼:

DataTable excelTable = new DataTable(); 

//a method that reads Excel doc and injects data into DataTable 
PopulateFromExcel(excelTable); 

DataView dv = new DataView(excelTable); 
dv.RowFilter = "a = 'categoryA' AND b= 'typeA'"; 
var match = dv.Count > 0; 
+0

感謝您的建議,我想我可以看到你要去哪裏。使用RowFilter方法,這是否意味着我不需要指定要搜索的列?我知道一點SQL,但對DataTable沒有太多的瞭解。 RowFilter只是說,如果兩個字符串出現在同一行,那麼就有一個匹配? – sora0419

+0

@ sora0419:對,你可以做查詢動態的,所以根據當前值生成查詢並獲取請求的數據。它本身不是一個SQL,但它可能更類似於宏本身使用Excel本身。 – Tigran

0

我會建議使用DOCMD.TransferSpreadsheet方法和Excel數據導出到訪問,並做一些simplet quering以符合您的要求。

1

我有兩個建議:一是優化效率,而其他優化內存使用


如果你做大量的查找,最有效的數據結構可能是一個元組的的HashSet。以下是一個示例:

var set = new HashSet<Tuple<string, string>>(); 

set.Add(Tuple.Create("categoryA", "typeA")); 
set.Add(Tuple.Create("categoryA", "itemA")); 
set.Add(Tuple.Create("typeA", "itemA")); 
set.Add(Tuple.Create("categoryA", "typeB")); 
set.Add(Tuple.Create("categoryA", "typeC")); 
set.Add(Tuple.Create("categoryA", "itemB")); 
... 

var found1 = set.Contains(Tuple.Create("categoryA", "typeC")); // yields True 
var found2 = set.Contains(Tuple.Create("itemA", "itemB")); // yields False 

當您讀取數據時,將爲每行添加應將True設置爲HashSet的所有可能組合。這將是相當大的,但查找操作應該幾乎是瞬間的。


或者,你可以創建一個類MyRow與領域CategoryTypeItem和數據存儲在List<MyRow>。然後,你可以使用LINQ找到匹配的記錄:

var isMatch = myList.Any(row => (row.Category == string1 && row.Type == string2) 
          || (row.Category == string1 && row.Item == string2) 
          || ...); 

這需要最少的內存(因爲每個值只存儲一次)。但是,每個搜索操作都會遍歷完整列表,直到找到匹配項。

+0

感謝您的建議。我認爲你的想法有點類似於我原來的想法,存儲所有可能的配對。我不想有一個大的桌子/字典,所以我想要其他的可能性。謝謝:) – sora0419

+0

@ sora0419:我剛剛添加了一個將數據存儲在一個小列表中的可能性。 – Heinzi