我只想问:
我们需要使用包含类似(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;
}
}
}
}
答案 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)
您的代码中存在大量问题和效率低下。
如果您要创建多个词典,请直接创建词典。请勿使用单独的实例填充值并从中复制。
永远不要在这样的循环中使用字符串连接。使用StringBuilder
或其他类似机制来构建字符串。您已经在集合中拥有了您的值,因此将String.Join()
与LINQ结合使用会清除它。
从字典中获取值的方法至少可以说是尴尬。通常,您只能单独使用TryGetValue()
来尝试读取密钥。您的代码使用不正确。如果您要检查字典中是否存在密钥(使用Contains()
),那么使用TryGetValue()
就没有意义了。更糟糕的是,你做了这个然后通过迭代键值对在内部字典中手动搜索键。
典型的模式如下:
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();
嵌套字典并不是一件坏事,它是组织键和值层次结构的好方法。但为了保持可维护性,通常应将所有内容封装在另一个类中,提供操作数据的方法,而无需直接管理字典。您可以使其既高效又可维护。如何实现这一点是一项留给你的练习。