2014-01-24 118 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