如何从多维数组创建字符串向量?

时间:2014-07-31 21:23:04

标签: c# arrays algorithm multidimensional-array

最初的问题是我正在从正在开发的工具中读取大块二进制数据。

我的目标是读取数据并将其解析为人类可读的文本,例如.csv文件,所以我必须弄平 那个数据。

数据是浮点数,长数或整数或其他数据的多维数组的样本形式。和 因为该工具正在开发中,所以阵列的大小和尺寸可能因时而异!

(例如,我现在可能有2 * 2矩阵的样本,从现在起两小时后他们可能会将数据结构更改为 1 * 4,或16 * 12 * 128的数组,......)

问题的一部分是生成.CSV文件的标题行。我需要一种可以的方法 生成一个像这样的字符串数组:

表示2 * 2:data_0_0,data_0_1,data_1_0,data_1_1和

表示1 * 4:data_0,data_1,data_2,data_3,

表示3 * 4 * 2:data_0_0_0,data_0_0_1,data_0_0_2,....,data_2_3_0,data_2_3_1,

依旧......

每次我从工具中获得的唯一信息是数组的尺寸和大小。 该工具可能告诉我{1},这意味着单个值,{12}表示长度为12的数组,{3,4,5} 意思是" 3x4x5"元素数组等等......因此,我需要能够展平任何数组 a * b * c * .. * x。 (这不应该太难,因为我可以有一个for循环。

所以,我想创建一个从ANY多维数组生成字符串向量(以上格式)的方法。

因此我认为最后,标题生成方法看起来与此类似

public string[] GenerateNames(string dataBlockName, int[] dimensions)
{




}

一个简单的解决方案是让我们说10个For循环,并希望原始数据永远不会有一个超过10维的数组。但是,我正在寻找更好,更清洁,更好的解决方案! 有很多问题要求如何将矢量更改为多维数组。我的目标是完全相反的事情和具有无限灵活性的标题行!

非常感谢fellas!

- 下面有人建议使用" Depth First Traversal"我现在要调查一下。最初的谷歌搜索似乎很有希望。

3 个答案:

答案 0 :(得分:1)

你可以通过在foreach循环中迭代它,将每个项目添加到列表,然后将该列表转换回数组来展平任何数组。

public T[] Flatten<T>(Array array)    
{
    var list = new List<T>();

    foreach (T item in array)
    {
        list.Add(item);
    }

    return list.ToArray();
}

其中array是任何形状的矩形数组。

答案 1 :(得分:0)

您不需要具有大小的数组,因为您可以使用Array类的Rank属性以及获取值的相应方法来检查维度。考虑到这一点以及良好的旧.net 1.0 Array类,您可以编写类似这样的方法:

public T[] Flatten<T>(Array source)
{
    var arrayIndex = new int[source.Rank];
    var result = new T[Enumerable.Range(0, source.Rank).Sum(i => source.GetUpperBound(i))];
    var index = 0;
    for(var i = 0; i < source.Rank; i++)
    {
        for(var j = 0; j < source.GetUpperBound(i); j++) 
        {
            arrayIndex[i] = j;
            result[index++] = (T)source.GetValue(arrayIndex);
        }
    }
    return result;
}

它比foreach更复杂,但它将为您如何遍历原始数组提供更大的灵活性(这取决于.net实现)。由于Array不是泛型类,因此您需要在方法上提供元素类型,以便对于整数数组,您可以将其称为:

Flatten<int>(myArray);

答案 2 :(得分:0)

Buffer.BlockCopy在这里很方便。

注意:有一些特殊情况要处理,所以把它作为伪代码。

public T[] Flatten<T>(Array source) 
{
   int byteCount = Buffer.ByteLength(source);  
   int sizeofT = Buffer.ByteLength(new T[1]);

    T[] dest = new T[(byteCount + sizeofT - 1) / sizeofT];  
    Buffer.BlockCopy(source,0,dest,0,byteCount);

    return dest;   
}