本质上,我需要的是将不同的 int 变量映射到字典。或者至少那是我想做的方式。我能想到的最简单的方法是使用 switch 语句来解释我想要的内容。
string s = "";
int a = 1;
int b = 2;
int c = 0;
switch (a){
case 0:
s = "a0";
break;
case 1:
switch (b){
case 0:
s = "b0";
break
case 1:
switch (c){
case 0:
s = "c0";
break;
case 1:
s = "c1";
break;
}
break
case 2:
s = "b2";
break;
}
break;
case 2:
s = "a2";
break;
}
为简洁起见,这是一个简化版本,否则您可能会有很多嵌套,并且在不止一种情况下等等。我在想一个很好的解决方案是使用字典来快速选择正确的值,但这并不能很好地嵌套,因为嵌套字典的大部分内部嵌套都不需要有值。
我首先想到字典的原因是因为类似于以下的声明语法会很好(这类似于字典的字典)。
thing = {
{0, "a0"},
{1, {
{0, "b0"},
{1, {
{0, "c0"},
{1, "c1"}
}
},
{2, "b2"}
}
},
{2, "a2"}
}
// Next line is sort of hopeful but potentially unrealistic syntax
s = thing[a][b][c]; // or = thing(a,b,c);
编辑:这不是必需的声明语法,但它简短易懂,这正是我正在寻找的。p>
编辑:或 LINQ,我已经看到很多针对类似问题的 LINQ 建议,但我并不是特别熟悉它。
最佳答案
鉴于您正在寻找键的部分匹配项,您将无法使用单个字典来完成此任务。原因如下:
假设您有某种“规则”类。我们称它为“ key ”。您可以像这样实例化它:
Key.Create(0) // this "rule" would match any query key starting with 0 (e.g., {0}, {0, 1}, or {0, 1, 9, 2, 23, 243})
现在假设您想使用某种“事实”或“查询键”类来查询它。由于您使用在 Add 操作期间用作键的值类型查询字典,因此您将不得不重用相同的类型:
Key.Create(0, 2, 13) // this fact should be matched by rules {0}, {0,2} or {0, 2, 13}
现在您将尝试获取值:
var value = map[Key.Create(0, 2, 13)]
Key 类可以覆盖 Equals 以允许部分键匹配。但是,字典将首先使用哈希码,而 Key.Create(0, 2, 13) 的哈希码永远不会与 Key.Create(0) 的哈希码相匹配。您也无法通过使用任何类型的基础/派生类型来解决这个问题。
最好的选择可能是推出自己的类(class)。应该这样做:
class ResultMap
{
public void Add(int[] key, string value)
{
Debug.Assert(key != null);
Debug.Assert(key.Length > 0);
var currentMap = _root;
foreach (var i in key.Take(key.Length - 1))
{
object levelValue;
if (currentMap.TryGetValue(i, out levelValue))
{
currentMap = levelValue as Dictionary<int, object>;
if (currentMap == null)
throw new Exception("A rule is already defined for this key.");
}
else
{
var newMap = new Dictionary<int, object>();
currentMap.Add(i, newMap);
currentMap = newMap;
}
}
var leaf = key[key.Length - 1];
if (currentMap.ContainsKey(leaf))
throw new Exception("A rule is already defined for this key.");
currentMap.Add(leaf, value);
}
public string TryGetValue(params int[] key)
{
Debug.Assert(key != null);
Debug.Assert(key.Length > 0);
var currentMap = _root;
foreach (var i in key)
{
object levelValue;
if (!currentMap.TryGetValue(i, out levelValue))
return null;
currentMap = levelValue as Dictionary<int, object>;
if (currentMap == null)
return (string) levelValue;
}
return null;
}
private readonly Dictionary<int, object> _root = new Dictionary<int, object>();
}
这是一个单元测试:
public void Test()
{
var resultMap = new ResultMap();
resultMap.Add(new[] {0}, "a0");
resultMap.Add(new[] {1, 0}, "b0");
resultMap.Add(new[] {1, 1, 0}, "c0");
resultMap.Add(new[] {1, 1, 1}, "c1");
resultMap.Add(new[] {1, 2}, "b2");
resultMap.Add(new[] {2}, "a2");
Debug.Assert("a0" == resultMap.TryGetValue(0));
Debug.Assert("a0" == resultMap.TryGetValue(0, 0));
Debug.Assert("a0" == resultMap.TryGetValue(0, 1));
Debug.Assert("a0" == resultMap.TryGetValue(0, 2));
Debug.Assert("a0" == resultMap.TryGetValue(0, 0, 0));
Debug.Assert("a0" == resultMap.TryGetValue(0, 0, 1));
Debug.Assert("a0" == resultMap.TryGetValue(0, 0, 2));
Debug.Assert("a0" == resultMap.TryGetValue(0, 1, 0));
Debug.Assert("a0" == resultMap.TryGetValue(0, 1, 1));
Debug.Assert("a0" == resultMap.TryGetValue(0, 1, 2));
Debug.Assert("a0" == resultMap.TryGetValue(0, 2, 0));
Debug.Assert("a0" == resultMap.TryGetValue(0, 2, 1));
Debug.Assert("a0" == resultMap.TryGetValue(0, 2, 2));
Debug.Assert(null == resultMap.TryGetValue(1));
Debug.Assert("b0" == resultMap.TryGetValue(1, 0));
Debug.Assert(null == resultMap.TryGetValue(1, 1));
Debug.Assert("b2" == resultMap.TryGetValue(1, 2));
Debug.Assert("b0" == resultMap.TryGetValue(1, 0, 0));
Debug.Assert("b0" == resultMap.TryGetValue(1, 0, 1));
Debug.Assert("b0" == resultMap.TryGetValue(1, 0, 2));
Debug.Assert("c0" == resultMap.TryGetValue(1, 1, 0));
Debug.Assert("c1" == resultMap.TryGetValue(1, 1, 1));
Debug.Assert(null == resultMap.TryGetValue(1, 1, 2));
Debug.Assert("b2" == resultMap.TryGetValue(1, 2, 0));
Debug.Assert("b2" == resultMap.TryGetValue(1, 2, 1));
Debug.Assert("b2" == resultMap.TryGetValue(1, 2, 2));
Debug.Assert("a2" == resultMap.TryGetValue(2));
Debug.Assert("a2" == resultMap.TryGetValue(2, 0));
Debug.Assert("a2" == resultMap.TryGetValue(2, 1));
Debug.Assert("a2" == resultMap.TryGetValue(2, 2));
Debug.Assert("a2" == resultMap.TryGetValue(2, 0, 0));
Debug.Assert("a2" == resultMap.TryGetValue(2, 0, 1));
Debug.Assert("a2" == resultMap.TryGetValue(2, 0, 2));
Debug.Assert("a2" == resultMap.TryGetValue(2, 1, 0));
Debug.Assert("a2" == resultMap.TryGetValue(2, 1, 1));
Debug.Assert("a2" == resultMap.TryGetValue(2, 1, 2));
Debug.Assert("a2" == resultMap.TryGetValue(2, 2, 0));
Debug.Assert("a2" == resultMap.TryGetValue(2, 2, 1));
Debug.Assert("a2" == resultMap.TryGetValue(2, 2, 2));
}
关于c#不同深度的嵌套字典,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/16925497/