【问题标题】:C# - Change a multi-dimensional Array element TypeC# - 更改多维数组元素类型
【发布时间】:2018-02-28 17:15:25
【问题描述】:

我有一个维度未知的多维数组在编译时,但在运行时(当我收到这样的数组时)它的维度被描述为int[] dimensionsdimensions 的长度等于 Array 的 Rank,dimensions 的每个元素都包含相关维度的长度。

我想要获得的是一个类似的 Array,其元素映射到具有不同类型的新对象中。我认为 LINQ 可能很有用,所以我写了以下内容:

Array arr = ... //My multi-dimensional Array
var dimensions = ... //array describing the dimensions of arr. (NOT USED in the following but is an information i have)

var transformedArr = arr.Cast<StatusCode>().Select(val => JObject.FromObject(val)).ToArray();

它可以工作,但 transformedArr 现在只是一个一维数组,因此我丢失了我的多维矩阵。 您是否知道仅获得具有不同元素类型的相同数组?

请注意,我不知道数组的先验维度,仅在运行时。换句话说,我不能使用循环来索引多维数组。

任何想法将不胜感激:)

【问题讨论】:

    标签: c# arrays multidimensional-array


    【解决方案1】:

    我认为以下功能应该满足您的要求

    public static void RecursiveCopy<TInput, TOutput>(
        Array source,
        Array destination,
        int[] dimensions,
        Func<TInput, TOutput> mutate,
        int[] indexPrefix = null)
    {
        indexPrefix = indexPrefix ?? new int[0];
        if (dimensions.Length != 1)
        {
            for (var i = 0; i < dimensions[0]; i++)
            {
                var newDimensions = new int[dimensions.Length - 1];
                Array.Copy(dimensions, 1, newDimensions, 0, dimensions.Length - 1);
    
                var newIndexPrefix = new int[indexPrefix.Length + 1];
                Array.Copy(indexPrefix, 0, newIndexPrefix, 0, indexPrefix.Length);
                newIndexPrefix[indexPrefix.Length] = i;
    
                RecursiveCopy(source, destination, newDimensions, mutate, newIndexPrefix);
            }
        }
        else
        {
            var currentIndex = new int[indexPrefix.Length + 1];
            Array.Copy(indexPrefix, 0, currentIndex, 0, indexPrefix.Length);
            for (var i = 0; i < dimensions[0]; i++)
            {
                currentIndex[indexPrefix.Length] = i;
                var value = source.GetValue(currentIndex);
                if (value is TInput)
                {
                    var mutated = mutate((TInput)value);
                    destination.SetValue(mutated, currentIndex);
                }
                else
                {
                    throw new ArgumentException("Different type. Expected " + nameof(TInput));
                }
            }
        }
    }
    

    用法

    var transformedArr = Array.CreateInstance(typeof(StatusCode), dimensions);
    RecursiveCopy<object, StatusCode>(arr, transformedArr, dimensions, i => i as StatusCode);
    

    你可以用真正的类型代替对象

    【讨论】:

    • 你拯救了我的一天!非常感谢。现在我必须明白你写了什么:D
    【解决方案2】:

    您可以使用CreateInstance 创建输出数组(使用dimensions 作为输入),然后使用GetValueSetValue 转换您的值。

    【讨论】:

    • 我不能使用 GetValue 和 SetValue,因为我在编译时不知道 Array 的尺寸。所以我不知道它是 2x3x5 还是 2x3x7x3 等。换句话说,我无法在代码中索引数组,因为我不知道我有多少维。我希望我很清楚。
    • 这些函数你看了吗?它们专为启用您的用例而设计。您可以使用索引数组,而无需编译时知道排名。
    • 我当然看过了。第二个参数是“一个 32 位整数的一维数组,表示指定要获取的 Array 元素位置的索引。”我无法传递索引,因为我不知道索引是如何组成的。
    猜你喜欢
    • 2023-03-25
    • 1970-01-01
    • 1970-01-01
    • 2019-01-15
    • 1970-01-01
    • 1970-01-01
    • 2019-09-09
    • 2020-01-12
    • 1970-01-01
    相关资源
    最近更新 更多