繁体   English   中英

返回n维数据结构?

[英]Returning an n-dimensional data structure?

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

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

这是不可能的,因为必须在编译时知道您的返回类型,但是您编写的伪代码取决于varIDs中的元素数量,直到运行时才知道。

不要听反对者的话;)是的,有一点调整是可能的。 这是一个有趣的问题,所以我想确定自己。

这是您要求的唯一方法:

    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");            
    }

这样的事情怎么样?

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

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM