philkark
philkark

Reputation: 2457

Smallest and biggest value in slice of 3D array

I have a 3d-array double[,,] numbers = new double[x,y,z]; and now if one imagines the 3d-array to look like a cube with numbers I need to find the smallest and biggest value of every slice along all three directions.

It is of course easy to do by simply looping over it, but does C# have any functions to find the smallest and biggest value in a slice?

To explain it a bit further, maybe this "unreal" code will help:

int i;

double[] xmin = new double[x];
double[] xmax = new double[x];
double[] ymin = new double[y];
double[] ymax = new double[y];
double[] zmin = new double[z];
double[] zmax = new double[z];

for(i = 0; i < x; i++)
{
    MinOf(numbers[i, y, z]) = xmin[i];
    MaxOf(numbers[i, y, z]) = xmax[i];
}

for(i = 0; i < y; i++)
{
    MinOf(numbers[x, i, z]) = ymin[i];
    MaxOf(numbers[x, i, z]) = ymax[i];
}

for(i = 0; i < z; i++)
{
    MinOf(numbers[x, y, i]) = zmin[i];
    MaxOf(numbers[x, y, i]) = zmax[i];
}

Hopefully someone can help me with that. Cheers, Phil13131

Upvotes: 1

Views: 1579

Answers (2)

dtb
dtb

Reputation: 217263

Are you looking for something like this?

double[, ,] numbers = new double[2, 2, 2];

numbers[0, 0, 0] = 0;
numbers[0, 0, 1] = 1;
numbers[0, 1, 0] = 2;
numbers[0, 1, 1] = 3;
numbers[1, 0, 0] = 4;
numbers[1, 0, 1] = 5;
numbers[1, 1, 0] = 6;
numbers[1, 1, 1] = 7;

double[] xmax = new double[numbers.GetLength(0)];
double[] ymax = new double[numbers.GetLength(1)];
double[] zmax = new double[numbers.GetLength(2)];

for (int x = 0; x < xmax.Length; x++) xmax[x] = int.MinValue;
for (int y = 0; y < ymax.Length; y++) ymax[y] = int.MinValue;
for (int z = 0; z < zmax.Length; z++) zmax[z] = int.MinValue;

for (int x = 0; x < xmax.Length; x++)
    for (int y = 0; y < ymax.Length; y++)
        for (int z = 0; z < zmax.Length; z++)
        {
            xmax[x] = Math.Max(xmax[x], numbers[x, y, z]);
            ymax[y] = Math.Max(ymax[y], numbers[x, y, z]);
            zmax[z] = Math.Max(zmax[z], numbers[x, y, z]);
        }

// xmax == { 3, 7 }
// ymax == { 5, 7 }
// zmax == { 6, 7 }

Upvotes: 2

Guffa
Guffa

Reputation: 700232

You can make methods for enumerating the slices. This is for one dimension, you would need another two, but I think you can manage that:

public static IEnumerable<T> SliceX<T>(T[,,] data, int x) {
  for (int y = 0; y < data.GetLength(1); y++) {
    for (int z = 0; z < data.GetLength(2); z++) {
      yield return data[x, y, z];
    }
  }
}

Then you can just use the Min and Max methods, but that will of course loop through the data twice:

double min = SliceX(numbers, x).Min();
double max = SliceX(numbers, x).Max();

You can make an extension method that gets both min and max in one iteration:

public static class IEnumerableExtensions {

  public static void GetMinMax<T>(this IEnumerable<T> data, out T min, out T max) where T : IComparable<T> {
    bool first = true;
    min = max = default(T);
    foreach (T value in data) {
      if (first) {
        min = max = value;
        first = false;
      } else {
        if (value.CompareTo(min) < 0) min = value;
        if (value.CompareTo(max) > 0) max = value;
      }
    }
  }

}

Usage:

double min, max;
SliceX(numbers, 0).GetMinMax(out min, out max);

Upvotes: 2

Related Questions