这是方法体中多键字典的有效代码吗?

时间:2011-09-12 21:48:37

标签: c# .net-3.5 dictionary

我只想问:

  1. 以下代码是否有效?
  2. 有没有更好的方法来解决这个问题?
  3. 如果需要表名/字段名对的其他值,如何编码?
  4. 我们需要使用包含类似(TableName,FieldName,FieldValue)之类的多键字典。

    我搜索了一些答案,但到目前为止我找到的答案并不适用于我们的设置。我们使用的是3.5,所以还没有Tuple可用。我们还将此脚本逻辑与仅允许在方法体内“编码”的应用程序集成,因此我们受到限制,无法创建单独的类/结构等。我们的设置是C#/ VS 2010。

    感谢任何帮助。提前谢谢!

    Dictionary<string, Dictionary<string, string>> tableList = new Dictionary<string, Dictionary<string, string>>();
    Dictionary<string, string> fieldList = new Dictionary<string, string>();
    
    // add fields to field list, then add the field lists to the corresponding table list
    // clear field list for next table
    // values are just hardcoded here to simplify, but is being read from actual objects in the application
    
    fieldList.Add("Field1", "abc");
    fieldList.Add("Field2", "def");
    fieldList.Add("Field3", "ghi");
    fieldList.Add("Field4", "jkl");
    
    tableList.Add("Table1", new Dictionary<string, string>(fieldList));
    fieldList.Clear();
    
    fieldList.Add("Field1", "xyz");
    fieldList.Add("Field2", "uvw");
    fieldList.Add("Field3", "rst");
    
    tableList.Add("Table2", new Dictionary<string, string>(fieldList));
    fieldList.Clear();
    
    fieldList.Add("Field1", "123");
    fieldList.Add("Field2", "456");
    
    tableList.Add("Table3", new Dictionary<string, string>(fieldList));
    fieldList.Clear();
    
    // Display tables and corresponding fields                          
    
    foreach (KeyValuePair<string, Dictionary<string, string>> fieldList4 in tableList)
    {
        foreach (KeyValuePair<string, string> fieldList5 in fieldList4.Value)
        {
            txtMessage.Text = txtMessage.Text + "\r\nTable=" + fieldList4.Key + ", Field=" + fieldList5.Key + " - " + fieldList5.Value;
        }
    }
    
    // Try to find tables and fields in the lists, and list the value if found
    
    string tableToFind = "Table2";
    string fieldToFind = "Field2";
    Dictionary<string, string> tableFields = new Dictionary<string, string>();
    
    if (tableList.Keys.Contains(tableToFind) == true)
    {
        txtMessage.Text = txtMessage.Text = "\r\nTable=" + tableToFind + " exist in table list";
        tableList.TryGetValue(tableToFind, out tableFields);
    
        if (tableFields.Keys.Contains(fieldToFind) == true)
        {
            foreach(KeyValuePair<string, string> fieldData  in tableFields)
            {
                if (fieldData.Key == fieldToFind)
                {
                    txtMessage.Text = txtMessage.Text + "\r\nTable=" + tableToFind + ", Field=" +  fieldData.Key + 
                                                        " with value=" + fieldData.Value + " exist in table list";
                    break;
                }
            }
        }
    }
    

3 个答案:

答案 0 :(得分:4)

您可以使用编译器为您创建复合键:使用匿名类型。

var dictionary = new Dictionary<Object, int>();

dictionary.Add(new{Text="A", Number=1}, 1);
dictionary.Add(new{Text="A", Number=2}, 3);
dictionary.Add(new{Text="B", Number=1}, 4);
dictionary.Add(new{Text="B", Number=2}, 5);

var x = dictionary[new{Text="B", Number=2}];

C#将根据您的字段实现Equals和GetHashcode。因此,您确实得到了一个符合您期望的键。

答案 1 :(得分:2)

我不认为这么多词典会“高效”。

我认为最好的方法是多次将值添加到同一个字典中 - 假设您希望能够根据其中一个指标(并非全部)对其进行索引:

dictionary.Add("FField1", "xxx");
dictionary.Add("TTable1", "xxx");

否则,如果要根据所有指标将它们编入索引,请使用加入字符(如'\0')。

dictionary.Add("Table1\0Field1", "xxx");

答案 2 :(得分:2)

您的代码中存在大量问题和效率低下。

  1. 如果您要创建多个词典,请直接创建词典。请勿使用单独的实例填充值并从中复制。

  2. 永远不要在这样的循环中使用字符串连接。使用StringBuilder或其他类似机制来构建字符串。您已经在集合中拥有了您的值,因此将String.Join()与LINQ结合使用会清除它。

  3. 从字典中获取值的方法至少可以说是尴尬。通常,您只能单独使用TryGetValue()来尝试读取密钥。您的代码使用不正确。如果您要检查字典中是否存在密钥(使用Contains()),那么使用TryGetValue()就没有意义了。更糟糕的是,你做了这个然后通过迭代键值对在内部字典中手动搜索键。

  4. 典型的模式如下:

    DictValueType value;
    if (myDict.TryGetValue(key, out value))
    {
        // key was in the dictionary, the value is stored in the `value` variable
    }
    

    你所拥有的代码可以更有效地写成 ,如下所示:

    var tableList = new Dictionary<string, Dictionary<string, string>>
    {
        { "Table1", new Dictionary<string, string>
                    {
                        { "Field1", "abc" },
                        { "Field2", "def" },
                        { "Field3", "ghi" },
                        { "Field4", "jkl" },
                    }
        },
        { "Table2", new Dictionary<string, string>
                    {
                        { "Field1", "xyz" },
                        { "Field2", "uvw" },
                        { "Field3", "rst" },
                    }
        },
        { "Table3", new Dictionary<string, string>
                    {
                        { "Field1", "123" },
                        { "Field2", "456" },
                    }
        },
    };
    
    // Display tables and corresponding fields
    txtMessage.Text = String.Join("\r\n",
        tableList.SelectMany(table =>
            table.Value.Select(fieldList =>
                String.Format("Table={0}, Field={1} - {2}",
                    table.Key, fieldList.Key, fieldList.Value)
            )
        ).ToArray()
    );
    
    // (I hope you have this in a separate method)
    // Try to find tables and fields in the lists, and list the value if found
    string tableToFind = "Table2";
    string fieldToFind = "Field2";
    
    var builder = new StringBuilder(txtMessage.Text); // mostly useful if you have a 
                                                      // lot of different strings to add
    Dictionary<string, string> foundTable;
    if (tableList.TryGetValue(tableToFind, out foundTable))
    {
        builder.AppendLine()
            .Append("Table=" + tableToFind + " exist in table list");
    
        string foundField;
        if (foundTable.TryGetValue(fieldToFind, out foundField))
        {
            builder.AppendLine()
                .AppendFormat("Table={0}, Field={1} with value={2} exist in table list",
                    tableToFind, fieldToFind, foundField);
        }
    }
    txtMessage.Text = builder.ToString();
    

    嵌套字典并不是一件坏事,它是组织键和值层次结构的好方法。但为了保持可维护性,通常应将所有内容封装在另一个类中,提供操作数据的方法,而无需直接管理字典。您可以使其既高效又可维护。如何实现这一点是一项留给你的练习。