views:

566

answers:

4

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  A: 
double[][] myArr = Enumerable
  .Range(0, rowCount)
  .Select(i => new double[colCount])
  .ToArray();
David B
+2  A: 

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 David 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();
Jeff Yates
+1 for LINQ is not the right tool.
Daniel Brückner
exact same answer as mine... but you were quicker ;)
Thomas Levesque
Great minds think alike, it seems :)
Jeff Yates
A: 

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
A: 

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