将二维数组转换

28

selectMany.ToArray() 方法是什么?它是 C# 自带的吗?

我需要将二维数组转换为一维数组。

4个回答

66
如果您指的是“不规则”数组(T[][]),那么SelectMany可以帮助您。但是,如果您指的是“矩形”数组(T[,]),您可以通过foreach枚举数据 - 或者:
int[,] from = new int[,] {{1,2},{3,4},{5,6}};
int[] to = from.Cast<int>().ToArray();

3
这个帖子,https://dev59.com/7W435IYBdhLWcg3w7ksK,详细介绍了如何使用foreach方法以及一些性能指标。 - ShawnFeatherly
2
我从不知道int[,]通过Cast()会转换成IEnumerable<int>。太酷了! - Mike
请记住,如果 from 是只读的,那么此方法将失败。 - Chmielok
@Chmielok,你能给个例子说明一下你的意思吗?如果“from”是只读字段,那么它应该可以正常工作;而且据我所知,“ImmutableArray<T>”仅支持向量。那么,你描述的是哪种失败情况呢? - Marc Gravell

30

SelectMany是一个投影运算符,由命名空间System.Linq提供的扩展方法。

它在序列中执行一对多元素投影,允许将结果序列“展平”为一个序列。

您可以按照以下方式使用它:

int[][] twoDimensional = new int[][] { 
                                      new int[] {1, 2},
                                      new int[] {3, 4},
                                      new int[] {5, 6}
                                     };

int [] flattened = twoDimensional.SelectMany(x=>x).ToArray();

13
吹毛求疵一点,我不会称之为二维数组,而是嵌套数组。 - Marc Gravell
1
@MarcGravell,不确定您为什么提到 int[][][]。我并不是在谈论他可能实现某些东西的不同方式。我只是想说,一个数组的数组是一个二维数组,即使这个数组是不规则的。当我提到立方体时,有点多余了,但我的观点是,一个三维的不规则数组不是一个立方体,但它仍然有三个维度。就像一个二维的不规则数组不是一个矩形数组,但它仍然有两个维度。称其为二维并不意味着它不可能是不规则的。我也在谈论我们如何称呼那个外部数组,您也是这样做的。 - barlop
@barlop,从技术上讲,我们都在谈论的外部数组是一个一维向量(引用本身也是向量)。抱歉,但事实就是这样。 - Marc Gravell
1
@MarcGravell 是的,我不否认这一点。内存是线性的,一维的,也许可以说是二维的。但肯定不是三维的。多维数组的概念是一个抽象的概念。我不知道 [,] 或者 [,,,]` 数组是如何存储的,但是即使它不是作为数组的数组进行存储,对于那些矩形或者 'cube' 数组来说,多维数组是一个抽象概念也同样成立。你使用的术语是基于抽象概念的,比如 jagged array,而你提到的二维数组也暗示了你接受这种抽象术语。所以我不知道你为什么要提及你提到的东西。 - barlop
让我们在聊天中继续这个讨论 - barlop
显示剩余3条评论

0

这个解决方案旨在将任何类型的int数组,包括常规、锯齿形和嵌套数组(后者来自JavaScript及其对象表示法,但也可以实现为C#中复杂的锯齿形对象数组),转换为简单的一维整数数组:

    public static int[] getFlattenedIntArray(object jaggedArray)
    {

        var flattenedArray = new List<int>();

        var jaggedArrayType = jaggedArray.GetType();
        var expectedType = typeof(int);

        if (jaggedArrayType.IsArray)
        {
            if (expectedType.IsAssignableFrom(jaggedArrayType.GetElementType()))
            {
                foreach (var el in jaggedArray as int[])
                {
                    flattenedArray.Add(el);
                }
            }
            else
            {
                foreach (var el in jaggedArray as object[])
                {
                    foreach (var retIntEl in getFlattenedIntArray(el))
                    {
                        flattenedArray.Add(retIntEl);
                    }
                }

            }
        }
        else if (jaggedArrayType == expectedType)
        {
            flattenedArray.Add((int)jaggedArray);
        }
        else
        {
            return new int[0];
        }

        return flattenedArray.ToArray();
    }

可以使用这个fiddle进行尝试:https://dotnetfiddle.net/5HGX96


-1

我的解决方案:

public struct Array3D<T>
{
    public T[] flatten;
    int x_len;
    int y_len;
    int z_len;

    public Array3D(int z_len, int y_len, int x_len)
    {
        this.x_len = x_len;
        this.y_len = y_len;
        this.z_len = z_len;
        flatten = new T[z_len * y_len * x_len];
    }

    public int getOffset(int z, int y, int x) => y_len * x_len * z + x_len * y + x;

    public T this[int z, int y, int x] {
        get => flatten[y_len * x_len * z + x_len * y + x];
        set => flatten[y_len * x_len * z + x_len * y + x] = value;
    }

    public T this[int flat_index] {
        get => flatten[flat_index];
        set => flatten[flat_index] = value;
    }
}

这与问题“将二维数组转换为一维数组”有什么确切的关系? - Adrian Pop
使用二维数组而不是一维数组类,可以轻松地“转换”为一维数组,而不会有性能上的劣势。 - iperov
转换为2D相当容易。 - iperov

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接