我有以下C#函数系列:
// 1D version
public Dictionary<int, double> GetNumCases1D(string varID1)
{
Dictionary<int, double> cases1D = new Dictionary<int, double>();
foreach (int value1 in ValuesFromVariable(varID1))
{
// do work
}
return cases1D;
}
// 2D version
public Dictionary<int, Dictionary<int, double>> GetNumCases2D(string varID1, string varID2)
{
Dictionary<int, Dictionary<int, double>> cases2D = new Dictionary<int, Dictionary<int, double>>();
foreach (int value2 in ValuesFromVariable(varID2))
{
// do work
Dictionary<int, double> cases1D = new Dictionary<int, double>();
foreach (int value in ValuesFromVariable(varID1))
{
// do more work
}
}
return cases2D;
}
// 3D version
public Dictionary<int, Dictionary<int, Dictionary<int, double>>> GetNumCases3D(string varID1, string varID2, string varID3)
{
Dictionary<int, Dictionary<int, Dictionary<int, double>>> cases3D = new Dictionary<int, Dictionary<int, Dictionary<int, double>>>();
foreach (int value3 in ValuesFromVariable(varID3))
{
// do work
Dictionary<int, Dictionary<int, double>> cases2D = new Dictionary<int, Dictionary<int, double>>();
foreach (int value2 in ValuesFromVariable(varID2))
{
// do more work
Dictionary<int, double> cases1D = new Dictionary<int, double>();
foreach (int value in ValuesFromVariable(varID1))
{
// do more work^2
}
}
}
return cases3D;
}
我想要的是一个单一的函数版本,它可以返回一个任意尺寸的数据结构,并带有相应数量的内部循环:
// n-dimensional version
public Dictionary<int, Dictionary<int, ... Dictionary<int, double>...>> GetNumCasesND(List<string> varIDs)
{
Dictionary<int, Dictionary<int, ... Dictionary<int, double>...>> casesND = new Dictionary<int, Dictionary<int, ... Dictionary<int, double>...>>();
foreach (int value1 in ValuesFromVariable(varIDs[0]))
{
// ??
foreach (int value2 in ValuesFromVariable(varIDs[1]))
{
// ??
...
foreach (int valueN in ValuesFromVariable(varIDs[N-1]))
{
// ??
}
}
}
return casesND;
}
这看起来不太可能 - 是吗?还有更好的方法吗?
答案 0 :(得分:3)
这是不可能的,因为你的返回类型必须在编译时知道,但是你编写的伪代码取决于varIDs
中直到运行时才知道的元素数。
答案 1 :(得分:1)
不要听取反对者的意见;)是的,有可能通过小调整。这是一个有趣的问题,所以我想确定自己。
这是您要求的单一方法:
public Dictionary<int, object> GetNumCasesNDim(params string[] input)
{
var result = new Dictionary<int, object>();
int dimensions = input.Length;
if (dimensions == 1)
{
foreach (int value in ValuesFromVariable(input[dimensions - 1]))
{
result.Add(value, 0.01d /*dummy double*/);
}
}
else
{
foreach (int value in ValuesFromVariable(input[dimensions - 1]))
{
var nextParams = new List<string>(input);
nextParams.RemoveAt(nextParams.Count - 1);
result.Add(value, GetNumCasesNDim(nextParams.ToArray()));
}
}
return result;
}
测试代码,与您自己的3D方法进行比较。我冒昧地用虚拟数据填补空白。
// 3D version
public Dictionary<int, Dictionary<int, Dictionary<int, double>>> GetNumCases3D(string varID1, string varID2, string varID3)
{
var cases3D = new Dictionary<int, Dictionary<int, Dictionary<int, double>>>();
foreach (int value3 in ValuesFromVariable(varID3))
{
var cases2D = new Dictionary<int, Dictionary<int, double>>();
cases3D[value3] = cases2D;
foreach (int value2 in ValuesFromVariable(varID2))
{
var cases1D = new Dictionary<int, double>();
cases2D[value2] = cases1D;
foreach (int value in ValuesFromVariable(varID1))
{
cases1D.Add(value, value + 0.1d);
}
}
}
return cases3D;
}
private static int nIndex;
private List<int> ValuesFromVariable(string s)
{
var result = new List<int>();
for (int i = 0; i < s.Length; ++i)
result.Add(++nIndex);
return result;
}
// n-dimensional version
public Dictionary<int, object> GetNumCasesNDim(params string[] input)
{
var result = new Dictionary<int, object>();
int dimensions = input.Length;
if (dimensions == 1)
{
foreach (int value in ValuesFromVariable(input[dimensions - 1]))
{
result.Add(value, 0.01d);
}
}
else
{
foreach (int value in ValuesFromVariable(input[dimensions - 1]))
{
var nextParams = new List<string>(input);
int index = nextParams.Count - 1;
nextParams.RemoveAt(index);
result.Add(value, GetNumCasesNDim(nextParams.ToArray()));
}
}
return result;
}
private void test()
{
nIndex = 0;
var dim3 = GetNumCases3D("this", "is", "a");
nIndex = 0;
var testDimN = GetNumCasesNDim("this", "is", "a");
nIndex = 0;
var test2DimN = GetNumCasesNDim("this", "is", "a", "test");
}
答案 2 :(得分:1)
这样的事情怎么样?
class MultidimensionalArray<TKey, TValue>
{
private readonly Dictionary<string, TValue> _impl = new Dictionary<string, TValue>();
public TValue this[IEnumerable<TKey> index]
{
get { return _impl[ToStringKey(index)]; }
set { _impl[ToStringKey(index)] = value; }
}
public TValue this[params TKey[] index]
{
get { return this[index.AsEnumerable()]; }
set { this[index.AsEnumerable()] = value; }
}
private string ToStringKey(IEnumerable<TKey> key)
{
return string.Join(";", key.Select(k => k.ToString()));
}
}
<强>用法:强>
var arr = new MultidimensionalArray<int, double>();
arr[1, 2, 3] = 3.5;
Console.WriteLine(arr[1, 2, 3]);
轻松扩展:
class MultidimensionalArray<TValue>: MultidimensionalArray<object, TValue> {}
<强>用法:强>
var arr = new MultidimensionalArray<double>();
arr['Y', "Hell", 0] = 3.5;
Console.WriteLine(arr['Y', "Hell", 0]);
另一种方法是使用dynamic
。