C#:将嵌套列表转换为nd数组
我想将具有任意多个嵌套级别的C#:将嵌套列表转换为nd数组,c#,arrays,list,nested,type-conversion,C#,Arrays,List,Nested,Type Conversion,我想将具有任意多个嵌套级别的T类型的嵌套列表转换为T类型的多维数组 这与此完全相同,但具有任意多个级别,这意味着递归 如何使用C#实现这一点 例如,我的类型是 List<List<List<List<int>>>> 列表 并且希望是int[][]或int[,,],最好是后者 这当然是假设每个兄弟姐妹列表的大小相同 这是一个n维的解决方案。 我用MakeList()为您的示例创建了一个4维的假列表 关键是首先找到维度及其大小,这是在CountD
T
类型的嵌套列表转换为T
类型的多维数组
这与此完全相同,但具有任意多个级别,这意味着递归
如何使用C#实现这一点
例如,我的类型是
List<List<List<List<int>>>>
列表
并且希望是int[][]
或int[,,]
,最好是后者
- 这当然是假设每个兄弟姐妹列表的大小相同
- 这是一个n维的解决方案。
我用MakeList()为您的示例创建了一个4维的假列表
关键是首先找到维度及其大小,这是在CountDimensions中完成的。
此维度数组允许您使用array.CreateInstance创建所需大小的数组
然后,我通过创建一个索引数组来循环遍历所有值,该数组以1乘1递增,当一个索引满时传播到下一个维度。
通过使用GetListValue递归,使用相同的索引数组挖掘列表
这可能不是最佳的性能,但这应该给你一个开始
using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
namespace NestedList
{
public class ListToArray
{
public Array Convert(IList input)
{
var dimensions = CountDimensions(input).ToArray();
var result = Array.CreateInstance(typeof(int), dimensions);
var indexes = new int[dimensions.Length];
while (indexes[0] < dimensions[0])
{
var currentValue = GetListValue(input, indexes, 0);
result.SetValue(currentValue, indexes);
// Inc last index, propagate to higher if needed
IncrementIndex(indexes, dimensions);
}
return result;
}
private int GetListValue(IList input, int[] indexes, int depth)
{
if (input[indexes[depth]] is IList sublist)
{
return GetListValue(sublist, indexes, depth + 1);
}
return (int)input[indexes[depth]];
}
private void IncrementIndex(int[] indexes, int[] dimensions)
{
var iIndex = indexes.Length - 1;
indexes[iIndex] = indexes[iIndex] + 1;
while (iIndex > 0 && indexes[iIndex] > dimensions[iIndex]-1)
{
indexes[iIndex] = 0;
iIndex--;
indexes[iIndex] = indexes[iIndex] + 1;
}
}
private IEnumerable<int> CountDimensions(IList input)
{
yield return input.Count;
if (input.Count > 0 && input[0] is IList sublist)
{
foreach (var value in CountDimensions(sublist))
{
yield return value;
}
}
yield break;
}
}
public class Program
{
static void Main()
{
var dec = new ListToArray();
var array = dec.Convert(MakeList());
}
private static List<List<List<List<int>>>> MakeList()
{
const int dim1 = 3;
const int dim2 = 4;
const int dim3 = 2;
const int dim4 = 5;
var nextValue = 0;
var dim1List = new List<List<List<List<int>>>>();
for (var x1 = 0; x1 < dim1; ++x1)
{
var dim2List = new List<List<List<int>>>();
for (var x2 = 0; x2 < dim2; ++x2)
{
var dim3List = new List<List<int>>();
for (var x3 = 0; x3 < dim3; ++x3)
{
var dim4List = new List<int>();
for (var x4 = 0; x4 < dim4; ++x4)
{
var element4 = nextValue++;
dim4List.Add(element4);
}
dim3List.Add(dim4List);
}
dim2List.Add(dim3List);
}
dim1List.Add(dim2List);
}
return dim1List;
}
}
}
使用系统;
使用系统集合;
使用System.Collections.Generic;
使用System.Linq;
命名空间嵌套列表
{
公共类ListToArray
{
公共数组转换(IList输入)
{
var dimensions=CountDimensions(输入).ToArray();
var result=Array.CreateInstance(typeof(int),dimensions);
var索引=新的整数[dimensions.Length];
而(索引[0]<维度[0])
{
var currentValue=GetListValue(输入,索引,0);
结果.设置值(当前值、索引);
//Inc最后一个索引,如果需要,传播到更高的索引
增量索引(索引、维度);
}
返回结果;
}
私有int GetListValue(IList输入,int[]索引,int深度)
{
if(输入[索引[深度]]为IList子列表)
{
返回GetListValue(子列表、索引、深度+1);
}
返回(int)输入[索引[深度]];
}
私有void递增索引(int[]索引,int[]维度)
{
var iIndex=指数。长度-1;
指数[iIndex]=指数[iIndex]+1;
而(iIndex>0&&index[iIndex]>dimensions[iIndex]-1)
{
索引[iIndex]=0;
指数--;
指数[iIndex]=指数[iIndex]+1;
}
}
私有IEnumerable CountDimensions(IList输入)
{
收益返回输入。计数;
如果(input.Count>0&&input[0]是IList子列表)
{
foreach(CountDimensions中的var值(子列表))
{
收益回报值;
}
}
屈服断裂;
}
}
公共课程
{
静态void Main()
{
var dec=新的ListToArray();
var数组=dec.Convert(MakeList());
}
私有静态列表生成列表()
{
常数int dim1=3;
常数int dim2=4;
常数int dim3=2;
常数int dim4=5;
var nextValue=0;
var dim1List=新列表();
对于(变量x1=0;x1
编辑:我最初为另一个解决方案保留了一个变量,现在已删除。
int[][[]]
是一个锯齿状数组(数组的数组…),而不是int[,,,]
@DmitryBychenko编辑的多维数组。我不知道,我是从python来c#的。我不介意,但是我更喜欢多维的,我会创建一个具有属性子类的类,并像递归类一样处理解决方案。