У меня есть следующее семейство функций 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 ответа
Не слушайте скептиков;) Да, возможно, с небольшой корректировкой. Это был интересный вопрос, поэтому я сам хотел убедиться.
Это единственный метод, о котором вы просили:
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");
}
Это просто невозможно, потому что ваш возвращаемый тип должен быть известен во время компиляции, но псевдокод, который вы написали, зависит от количества элементов в varIDs
, которое неизвестно до времени выполнения.
Как насчет этого?
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
.
Похожие вопросы
Новые вопросы
c#
C# (произносится как «see Sharp») — это высокоуровневый мультипарадигменный язык программирования со статической типизацией, разработанный Microsoft. Код C# обычно нацелен на семейство инструментов и сред выполнения Microsoft .NET, которое включает в себя .NET, .NET Framework, .NET MAUI и Xamarin среди прочих. Используйте этот тег для ответов на вопросы о коде, написанном на C#, или о формальной спецификации C#.
GetNumCases()
, это проблема с тем, как вы представляете свои данные.Dictionary<int, Dictionary<int, Dictionary<int, double>>>
- ужасно плохой способ представления данных и должен быть наказан тюремным заключением. Вам нужно сесть и подумать, с какими данными вы имеете дело, и создать правильный набор классовstrongly typed
, которые представляют эти данные, вместо того, чтобы использовать словари иint
для всего.