11

I have a 2-dimensional jagged array (though it's always rectangular), which I initialize using the traditional loop:

var myArr = new double[rowCount][];
for (int i = 0; i < rowCount; i++) {
    myArr[i] = new double[colCount];
}

I thought maybe some LINQ function would give me an elegant way to do this in one statement. However, the closest I can come up with is this:

double[][] myArr = Enumerable.Repeat(new double[colCount], rowCount).ToArray();

The problem is that it seems to be creating a single double[colCount] and assigning references to that intsead of allocating a new array for each row. Is there a way to do this without getting too cryptic?

6 Answers6

26
double[][] myArr = Enumerable
  .Range(0, rowCount)
  .Select(i => new double[colCount])
  .ToArray();
Amy B
  • 108,202
  • 21
  • 135
  • 185
1

What you have won't work as the new occurs before the call to Repeat. You need something that also repeats the creation of the array. This can be achieved using the Enumerable.Range method to generate a range and then performing a Select operation that maps each element of the range to a new array instance (as in Amy B's answer).

However, I think that you are trying to use LINQ where it isn't really appropriate to do so in this case. What you had prior to the LINQ solution is just fine. Of course, if you wanted a LINQ-style approach similar to Enumerable.Repeat, you could write your own extension method that generates a new item, such as:

    public static IEnumerable<TResult> Repeat<TResult>(
          Func<TResult> generator,
          int count)
    {
        for (int i = 0; i < count; i++)
        {
            yield return generator();
        }
    }

Then you can call it as follows:

   var result = Repeat(()=>new double[rowCount], columnCount).ToArray();
Amy B
  • 108,202
  • 21
  • 135
  • 185
Jeff Yates
  • 61,417
  • 20
  • 137
  • 189
0

The behavior is correct - Repeat() returns a sequence that contains the supplied object multiple times. You can do the following trick.

double[][] myArr = Enumerable
    .Repeat(0, rowCount)
    .Select(i => new double[colCount])
    .ToArray();
Daniel Brückner
  • 59,031
  • 16
  • 99
  • 143
0

You can't do that with the Repeat method : the element parameter is only evaluated once, so indeed it always repeats the same instance. Instead, you could create a method to do what you want, which would take a lambda instead of a value :

    public static IEnumerable<T> Sequence<T>(Func<T> generator, int count)
    {
        for (int i = 0; i < count; i++)
        {
            yield return generator();
        }
    }

    ...

    var myArr = Sequence(() => new double[colCount], rowCount).ToArray();
Thomas Levesque
  • 286,951
  • 70
  • 623
  • 758
0

I just wrote this function...

    public static T[][] GetMatrix<T>(int m, int n)
    {
        var v = new T[m][];
        for(int i=0;i<m; ++i) v[i] = new T[n];
        return v;
    }

Seems to work.

Usage:

float[][] vertices = GetMatrix<float>(8, 3);
mpen
  • 272,448
  • 266
  • 850
  • 1,236
-1

What about

var myArr = new double[rowCount, colCount];

or

double myArr = new double[rowCount, colCount];

Reference: http://msdn.microsoft.com/en-us/library/aa691346(v=vs.71).aspx

  • 1
    This is not creating a jagged array, as is requested. – Servy Oct 07 '14 at 18:45
  • Sorry Servy, you're right. You've metionated the array is always rectangular, so why you need a jagged array? The arrays that fulfill the fisrt one positions are dynamically loaded or you're trying to avoid any kind of restriction, like memory? – Fernando Brustolin Jan 07 '15 at 15:22
  • It's not my program. I have no idea why he needs a jagged array over a multidimentional array. – Servy Jan 07 '15 at 15:28