1

Let say I got this function :

void int Calculate(double[] array) {}

And in my main I got this array:

double[,] myArray = new double[3,3];

How can I call Calculate(...) ?

I try (that's don't compile) :

double[] mySingleArray = myArray[0];

What I want to avoid is unnecessary loop (for).

I declare a regular array, but if a jagged array or any other type of array works better, it's fine for me.

I use c# 3.5

1
  • I'm curious to know what your calculate method does. I bet we could do it as a lambda expression use an IEnumerable aggregate extension. Commented Apr 24, 2009 at 14:10

4 Answers 4

6

First, let's declare your Calculate() method like this:

int Calculate(IEnumerable<double> doubles)

Don't worry, you can still pass an array to that code. You might also need IList<double>, but 9 times out of 10 the IEnumerable is good enough. The main thing is that this will let us use the yield keyword to slice up your array in an efficient way:

public static IEnumerable<T> Slice(this T[,] values)
{
    return Slice(values, 0, 0);
}

public static IEnumerable<T> Slice(this T[,] values, int index)
{
    return Slice(values, 0, index);
}

public static IEnumerable<T> Slice(this T[,] values, int dimension, int index)
{
    int length = values.GetUpperBound(dimension);
    int[] point = new int[values.Rank];
    point[dimension] = index;
    dimension = 1 - dimension;// only works for rank == 2
    for (int i = 0; i < length; i++)
    {
        point[dimension] = i;
         yield return (T)values.GetValue(point);
    }
}

It still needs some work because it only works with rank 2 arrays, but it should be fine for the example you posted.

Now you can call your calculate function like this:

Calculate(myArray.Slice(0));

Note that due to the way IEnumerable and the yield statement work the for loop in the code I posted is essentially free. It won't run until you actually iterate the items in your Calculate method, and even there runs in a "just-in-time" fashion so that the whole algorithm remains O(n).

It gets even more interesting when you share what your Calculate method is doing. You might be able to express it as a simple Aggregate + lambda expression. For example, let's say your calculate method returned the number of items > 5:

myArray.Slice(0).Count(x => x > 5);  

Or say it summed all the items:

myArray.Slice().Sum();
Sign up to request clarification or add additional context in comments.

1 Comment

This is certainly a better solution if the problem calls for a real multidimensional array and not a jagged one.
4

A jagged array works the way you want:

double[][] jaggedArray = new double[][100];
for (int i = 0; i < jaggedArray.Length; ++i)
    jaggedArray[i] = new double[100];

myFunction(jaggedArray[0]);

You can have different sizes for each array in this way.

2 Comments

Is there a way I can initialize my jagged array without using a for ? I mean something like : double[][] jaggedArray = new double[100][100]; ?
No, essentially, you are building an array of double[] objects. Those objects are totally unrelated to the original array.
0

A jagged array would let you split out the first array!

Comments

0

The Slice() method given above will get you a single row from your array, which seems to match the sample given in your question.

However, if you want a one dimensional array that contains all the elements in the rectangular array, you can use something like this, which is also O(n).

public static T[] Flatten<T>(this T[,] array) 
  where T : struct
{      
  int size = Marshal.SizeOf(array[0, 0]);
  int totalSize = Buffer.ByteLength(array);
  T[] result = new T[totalSize / size];
  Buffer.BlockCopy(array, 0, result, 0, totalSize);
  return result;      
}

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.