【问题标题】:Cross Index Referencing交叉索引引用
【发布时间】:2014-01-24 15:42:56
【问题描述】:

对不起,如果标题令人困惑,我不确定我应该如何标记它,我试过了。

我正在编写一个程序来执行一些交叉索引搜索,该程序是使用 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,则每个具有相同CATEGORYTYPEITEM 都是匹配项。

2) 如果字符串是TYPEITEM,则只有同一行中的其他数据是匹配的

这里有一些例子,字符串 a 和 b 是两个输入字符串,match 是一个布尔值:

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&lt;string, string&gt;,所以我可以在字典中搜索字符串a并获取匹配字符串列表并进行比较,但这样我将拥有一个巨大的字典和多个相同的键,这是行不通的。

感谢任何建议/帮助。

【问题讨论】:

    标签: c# string search data-structures cross-reference


    【解决方案1】:

    我会考虑使用System.Data 命名空间中的DataTable,它适合存储在内存中的表格数据。可能使它对您更具吸引力的是可以通过DataViewRowFilter 属性使用类似SQL 的查询来查询它。

    一些伪代码:

    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;
    

    【讨论】:

    • 感谢您的建议,我想我可以看到您的目标。使用 RowFilter 方法,这是否意味着我不需要指定要搜索的列?我对 SQL 了解一点,但对 DataTable 了解不多。 RowFilter 是否只是说如果两个字符串出现在同一行中则存在匹配?
    • @sora0419:正确,您可以进行动态查询,因此根据当前值生成查询并获取请求的数据。它本身不是 SQL,但有点类似于宏语言使用 Excel 本身。
    【解决方案2】:

    我有两个建议:一个优化效率,另一个优化内存使用


    如果您进行大量查找,最有效的数据结构可能是 元组哈希集。这是一个例子:

    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
    

    当您读取数据时,为每一行添加所有可能的组合,这些组合应该为 HashSet 产生 True。它会很大,但查找操作应该几乎是瞬时的。


    或者,您可以创建一个类MyRow,其中包含字段CategoryTypeItem,并将数据存储在List&lt;MyRow&gt; 中。然后,您可以使用 LINQ 查找匹配记录:

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

    这需要最少的内存(因为每个值只存储一次)。但是,每个搜索操作都会遍历完整列表,直到找到匹配项。

    【讨论】:

    • 感谢您的建议。我认为您的想法与我最初的想法有些相似,即存储每对可能的对。我不想有一张大桌子/字典,所以我在寻求其他可能性。谢谢:)
    • @sora0419:我刚刚添加了一种将数据存储在一个小列表中的可能性。
    【解决方案3】:

    我建议使用 DOCMD.TransferSpreadsheet 方法并导出 excel 数据以访问并执行一些简单的查询以满足您的要求。

    【讨论】:

      猜你喜欢
      • 2011-01-29
      • 1970-01-01
      • 1970-01-01
      • 2012-07-14
      • 2013-01-07
      • 1970-01-01
      • 2011-08-15
      • 2011-03-03
      • 2013-11-11
      相关资源
      最近更新 更多