28

What is selectMany.ToArray() method? Is it a built in method in C#?

I need to convert two dimensional array to one dimensional array.

gotqn
  • 42,737
  • 46
  • 157
  • 243
Manoj
  • 451
  • 1
  • 7
  • 8

4 Answers4

66

If you mean a jagged array (T[][]), SelectMany is your friend. If, however, you mean a rectangular array (T[,]), then you can just enumerate the date data via foreach - or:

int[,] from = new int[,] {{1,2},{3,4},{5,6}};
int[] to = from.Cast<int>().ToArray();
Gilad Green
  • 36,708
  • 7
  • 61
  • 95
Marc Gravell
  • 1,026,079
  • 266
  • 2,566
  • 2,900
  • 3
    This thread, http://stackoverflow.com/questions/5132397/fast-way-to-convert-a-two-dimensional-array-to-a-list-one-dimensional , goes into details of doing the foreach method and also some performance metrics. – ShawnFeatherly Feb 19 '16 at 09:07
  • 2
    I had no idea that `int[,]` gets converted into `IEnumerable` by `Cast()`. Cool trick! – Mike Apr 05 '19 at 10:46
  • Keep in mind that if `from` is readonly, this method will fail. – Chmielok Apr 30 '20 at 08:11
  • @Chmielok do you an example of what you mean there? if `from` is a readonly field, it should work fine; and AFAIK `ImmutableArray` only supports vectors; so: what scenario are you describing that fails? – Marc Gravell Apr 30 '20 at 11:08
30

SelectMany is a projection operator, an extension method provided by the namespace System.Linq.

It performs a one to many element projection over a sequence, allowing you to "flatten" the resulting sequences into one.

You can use it in this way:

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

int [] flattened = twoDimensional.SelectMany(x=>x).ToArray();
Christian C. Salvadó
  • 807,428
  • 183
  • 922
  • 838
  • 13
    Pedant point; that isn't what I'd call a 2-dimensional array - it is a jagged array... – Marc Gravell Mar 13 '09 at 05:22
  • @MarcGravell Isn't it a 2D jagged array? Clearly a jagged array is not a rectangular array or "cube" array. But it still has a degree of dimension. To say 2D array doesn't specify jagged or geometric/straight. – barlop Apr 29 '16 at 09:23
  • @barlop perhaps, but ultimately "the array" here would refer to to outer array, which is a vector of references; the jaggedness indeed makes it clear that it is more complex, and I would agree that in some ways "2D" could be used, as opposed to, say, an `int[][][]`. Ultimately, naming is hard :) – Marc Gravell Apr 29 '16 at 15:41
  • 1
    @MarcGravell not sure why you bring up `int[][][]`. I'm not really talking about different ways he could've implemented something. All i'm saying is that an array of an array, is a 2 dimensional array, even if [the] array of array is jagged. When I mentioned cube, it was a bit unnecessary, but my point was that a 3D jagged array isn't a cube but it's still 3 dimensions. Just as a 2D jagged array isn't a rectangular array, but it still has 2 dimensions. Calling it 2D doesn't preclude it from being jagged. I am also talking about how we refer to that outter array as you are too. – barlop Apr 29 '16 at 16:43
  • @barlop and technically, that outer array that we are both talking about: is a 1-dimensional vector (of references which just happen to themselves also be vectors). Sorry, but it is. That's just a statement of fact. – Marc Gravell Apr 29 '16 at 22:07
  • 1
    @MarcGravell yes i am not denying that. Memory is linear, 1D, perhaps arguably 2D. But definitely not ever 3D. The concept of a multidimensional array is an abstraction. I don't know how a `[,]` or [,,,]` array is stored, but even if it's not stored as array of array, that point about multi dimensional arrays being an abstraction is also the case for those rectangular or 'cube' arrays too. You are using terms that are based on abstract concepts, like jagged array, and your mention of 2D array suggests you accept that abstract terminology. So I don't know why you are mentioning what you are – barlop Apr 29 '16 at 23:29
  • @barlop because even in the abstraction: "the array" (the outer one) is notionally 1D, and is accessed as such. The fact that the things it contains are references to arrays doesn't change that. – Marc Gravell Apr 30 '16 at 07:59
  • Let us [continue this discussion in chat](http://chat.stackoverflow.com/rooms/110702/discussion-between-barlop-and-marc-gravell). – barlop Apr 30 '16 at 08:12
0

This solution is devoted to convert any sort of int array, regular, jagged, or nested (these last are taken from javascript and its object notation, but they can also be implemented as complex jagged array of objects in C#), into a simple mono-dimensional integers array:

    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();
    }

Try it with this fiddle: https://dotnetfiddle.net/5HGX96

Ciro Corvino
  • 2,038
  • 5
  • 20
  • 33
-1

my solution:

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;
    }
}
iperov
  • 455
  • 7
  • 8