Find length of specific dimension of 2D list - c#

I need to check the length of the first dimension of a 2 dimensional list of integers 'centreX1' before following loop:
for (x = 0; x < (int)centreX1[0].Count(); x++)
{
if (BinarySpotsInsideTolerance1[0][x] == 1)
{
AllspotsY.Add(centreY1[0][x]);
AllspotsX.Add(centreX1[0][x]);
AllspotsRLU.Add(RLUSpotsthreshold1[0][x]);
}
}
An error is thrown at centreX1[0].Count() if centreX1 has no members.

You can't count the number of elements in centreX1[0], if centreX1 has no elements.
Make sure centreX1 has elements in it, before trying to access the first one.
if (centreX1.Any()) // or "if (centreX1.Count() > 0)"
{
for (x = 0; x < (int)centreX1[0].Count(); x++)
{
if (BinarySpotsInsideTolerance1[0][x] == 1)
{
AllspotsY.Add(centreY1[0][x]);
AllspotsX.Add(centreX1[0][x]);
AllspotsRLU.Add(RLUSpotsthreshold1[0][x]);
}
}
}

Related

Parse 2d int array to List of BubbleDataPoints

I have an algorithm which makes use of a grid which is implemented via an int[,] in C#. I would like to graph the output in Blazor using the Bubble chart of blazor chart.Js. Preferably I would like to create separate datasets depending on the value of the int. 0 = empty/ignore, 1 = particular object type, 2 = particular object type.
I'm having an issue with picking out the data and converting it to the BubbleDataPoint(x,y,r) which the chart expects. I would like the x,y to correspond to the array index e.g. graph[1,1] = 1 would be bubbledatapoint(1,1,1) etc. I implemented an IEnumerable method in my class so that I could use foreach or .select on the int values but not sure how to get the array indices out.
public IEnumerable<int> GridValues()
{
for (int x = 0; x < grid.GetLength(0); x++)
{
for (int y = 0; x < grid.GetLength(1); y++)
{
yield return grid[x,y];
}
}
}
Thanks,
Ok, so for anyone interested I went with this method. I initially wanted to avoid looping over the array until I realised that 2D arrays don't implement IEnumerable and I was doing a half-way method but then just decided to go with this.
public IEnumerable<BubbleDataPoint> GridToDataPoints()
{
for (int x = 0; x < grid.GetLength(0); x++)
{
for (int y = 0; y < grid.GetLength(1); y++)
{
yield return new BubbleDataPoint(Convert.ToDouble(x), Convert.ToDouble(y), Convert.ToDouble(grid[x, y]));
}
}
}

Global array in recursive function issue

So i have a globar array and a recursive function. For example, recursive function performs itself 16 times, and bestOrder=array2D line should be reached only twice. Program actually reach it only twice, but bestOrder changes its value every time array2D is changed (array2D[position] = i;) in this line. BestOrder should contain 2 0 3 1 order, but at the end of the function it contains 3 2 1 0 (last value of the array2D). How can i fix that?
private static int[] bestOrder;
private static void Permutate(int[] array2D, int position, Point[] checkpoints)
{
if (position == array2D.Length)
{
if (GetPathLen(checkpoints, array2D) < min)
{
min = GetPathLen(checkpoints, array2D);
bestOrder= array2D;
}
return;
}
for (int i = 0; i < array2D.Length; i++)
{
bool found = false;
for (int j = 0; j < position; j++)
if (array2D[j] == i)
{
found = true;
break;
}
if (found) continue;
array2D[position] = i;
Permutate(array2D, position + 1, checkpoints);
}
}
Arrays are reference type means they are actually not copied when they are assigned to variables or passed to methods. Instead their references are passed (The pointer that points to same location in memory). One way is Clone and cast to actually copy the array.
bestOrder = (int[])array2D.Clone();
Another way is to create empty array. and fill it by elements of another array.
bestOrder = new int[array2D.Length];
for(int i = 0; i < bestOrder.Length; i++)
{
bestOrder[i] = array2D[i];
}

Populating one array with elements of another array. Exceeding the length of the second array exception

I have an assignment and I have come to a stumbling point where I get an exception that I am putting more elements in the array than in can hold. I have tried to make the array bigger, but it always goes beyond its bounds. Here is the code: .NetFiddle.
The problematic part starts on line 43 and the exception is thrown on line 52:
else
{
int x = 0;
int SumValue = 0;
int[] fibArray = new int[novArr.Length];
for (x = 0; x < novArr.Length-1; x++)
{
if (x + 1 < novArr.Length)
{
fibArray[SumValue] = novArr[x] - novArr[x + 1];
}
SumValue++;
}
Value = (fibArray.Max(element => Math.Abs(element)));
}

How to create Linked Array List in C#

I need to create an Array with Linked list capacities.
Basically, I need a static index based list (like array), but with the possibility to get next and previous field (and easily loop back and forward through list, like with linked list).
Note: Array is 2 dimensional. I use a custom class as array values. So I can set previous and next property for each instance.
Is there a built in C# collection for this? If not, any suggestions on how to create a very simple version of this? (I already have a version of this, consisting of 2 methods. One that loops forward to set the previous field, and one to loop backwards that set the next field, but it's still to messy).
Thanks in advance
EDIT:
The problem is my use of 2dimensional array. If loop through my array:
for (byte x = 0; x < Grid.GetLength(0); x++)
{
for (byte y = 0; y < Grid.GetLength(1); y++) /
{
//At certain point, I need to get the previous field. I can do:
if (y != 0)
{
y -= 2; //-2 because I will y++ in for. Already getting messy
}
else
{
//What if y == 0? Then I can't do y--. I should get max y and do x-- to get previous element:
y = (byte)(Grid.GetLength(1) - 1); //to get max value y
x--;
}
}
}
There is a built-in LinkedList<T> class.
But from your description why wouldn't an array work? It's static, and index-based, and you can easily get the next and previous element by incrementing / decrementing the index. It's hard to see exactly what you need from your code, but I'd like to point out that you can easily enumerate over a multi-dimensional array with:
var arry = new int[2,3];
foreach(var item in arry)
{
...
}
So you might be able to combine this with a Stack<T> structure (push items on the stack and pop them off to get the previous).
Alternatively, you can turn the array into a LinkedList directly.
var list = new LinkedList(arry.Cast<int>()); // flattens array
Or to preserve the indexes from the original array and still loop through the values as a linked list use:
var list = new LinkedList(arry.Cast<int>.Select((item, i) => new
{
Item = item,
Index1 = i % arry.GetLength(1),
Index2 = i / arry.GetLength(0)
}));
var node = list.First;
while(node.Next != null)
{
Console.WriteLine("Value # {1}, {2}: {0}", node.Value.Item, node.Value.Index1, node.Value.Index2);
// on some condition move to previous node
if (...)
{
node = node.Previous;
}
else
{
node = node.Next;
}
}
No, you don't. Instead of abandoning traditional arrays in lieu of "smart linked node arrays" which is what it seems like you're heading towards, try just adding a couple variables in your loop body:
byte x_len = Grid.GetLength(0);
byte y_len = Grid.GetLength(1);
byte prev_x, next_x, prev_y, next_y;
for (byte x = 0; x < x_len; ++x)
{
prev_x = x == 0? x_len - 1 : x - 1;
next_x = x == x_len - 1? 0 : x + 1;
for (byte y = 0; y < y_len; ++y)
{
prev_y = y == 0? y_len - 1 : y - 1;
next_y = y == y_len - 1? 0 : y + 1;
// here, you have access to the next and previous
// in both directions, satisfying your requirements
// without confusing your loop variables.
}
}

Index was outside of the bounds of the array [duplicate]

This question already has answers here:
What is an IndexOutOfRangeException / ArgumentOutOfRangeException and how do I fix it?
(5 answers)
Closed 7 years ago.
Unhandled Exception: System.IndexOutOfRangeException: Index was outside of the bounds of the array (at the first if statements)
static int arrayRows = 20;
static int arrayCols = 20;
public void printBoard()
{
int neighbours;
for (y = 0; y < arrayCols; y++)
for (x = 0; x < arrayRows; x++)
{
neighbours = 0;
// Count number of neighbours surrounding live cell
if (parentGen[x-1, y-1] == 1) // top left
neighbours++;
if (parentGen[x-1, y] == 1) // left
neighbours++;
if (parentGen[x-1, y+1] == 1) // bottom left
neighbours++;
if (parentGen[x, y-1] == 1) // middle top
neighbours++;
if (parentGen[x, y+1] == 1) // middle bottom
neighbours++;
if (parentGen[x+1, y-1] == 1) // top right
neighbours++;
if (parentGen[x+1, y] == 1) // right
neighbours++;
if (parentGen[x+1, y+1] == 1) // bottom right
neighbours++;
}
}
The only thing I can think of is that my program is checking coordinates of < 0? How do I go about fixing this?
Your first coordinates are parentGen[-1, -1], this will always throw the exception.
You need to check if the cell you're on has any neighbors to the left, right, top, or bottom. For example, x = 0 has no neighbors to the left and y = 20 has no neighbors to the bottom. You may wish to break this out to other functions, such as HasNeighborsLeft(int x), etc.
edit: sample code
if(x > 0 && y > 0 && parentGen[x - 1, y - 1] == 1)
{
neighbors++;
}
You can factor this out to it's own functions though, and you can wrap this kind of logic around all of the checks that involve x - 1 for example.
You need boundary condition checks on both x and y at top and bottom of their range. You cannot legally index the entire array using +1 and -1 offsets. Break up your check into boundary condition cases where x == 0, x == arrayRows-1 (by not checking the invalid relative offsets here), and then check cases where x+1 and x-1 are always valid in an else. Similarly with y.
You're array goes from 0->21. As well, you're testing values at [-1, -1] and [22, 22]You can fix it by chainging your for statement(s) to
for (int x = 1; x <= arrayCols - 1; x++)
for (int y = 1; y <= arrayRows - 1; y++)
In addition, problems with loops are almost always caused by a small number of cases that you can always check for:
Your for statement a) starts at a lower bound than the array, or b) finishes at a higher one
a) for (int x = -1;
b) for (int x = 0; x <= array.Length
Your code in the loop accesses values outside of your indexer range
for (int x = 0...
array[x-1, ...
Your collection isn't initialized
In this case, your problem 2.
The problem is that you are looking at the previous and next values (-1 and +1) which will obviously go outside the array bounds at either ends of the array.
There are a few options solving this:
Create a bigger array with a dummy 'border' around the edge which you don't use for your board but allows you to use code very similar to that which you have now (with your -1 and +1 previous and next cell logic). (Imagine a chess board that is 10x10 where you are not allowed to play in the outermost squares).
Scatter loads of 'if' statements to check if you're at the first or last item in the array and thus avoid making any array accesses that are invalid.
Create a function to retrieve an item at a particular cell and put conditional logic in this function for dealing with the array bounds.
Personally I would go with the last option, build yourself a function which gets the state of the specified cell, checks that the indices are valid and returns a default value if they are not. For example:
private const int EMPTY_CELL = 0;
private const int INVALID_CELL = EMPTY_CELL; // for now the same, but gives scope to handle separately
private int GetCellState(int row, int column)
{
if (row < 0) return INVALID_CELL;
if (column < 0) return INVALID_CELL;
if (row >= arrayRows) return INVALID_CELL;
if (column >= arrayColumns) return INVALID_CELL;
return parentGen[row, column];
}
It is then simply a matter of swapping your direct accesses to parentGen with calls to the function.
you could start by creating a sequence of only the valid indices and then iterate the combinations of those:
static int arrayRows = 20;
static int arrayCols = 20;
public void printBoard()
{
var sequences = from row in Enumerable.Range(0, arrayRows)
from column in Enumerable.Range(0, arrayCols)
select new
{
Rows = (from xs in new[] { row - 1, row, row + 1 }
where xs >= 0 && xs < 20
select xs),
Columns = (from ys in new[] { column - 1, column, column + 1 }
where ys >= 0 && ys < 20
select ys)
};
//now that we have a sequence with all the needed (valid) indices
//iterate through the combinations of those
var neighbours = (from seq in sequences
from row in seq.Rows
from column in seq.Columns
where row != column && parentGen[row, column] == 1
select 1).Count();
}

Categories

Resources