返回一个n维数据结构?

时间:2014-02-25 22:31:25

标签: c# dictionary

我有以下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;
}

这看起来不太可能 - 是吗?还有更好的方法吗?

3 个答案:

答案 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