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]));
}
}
}
Related
This question already has answers here:
List items changes as I add new data... why?
(6 answers)
Closed 6 years ago.
I need to create a dynamically sized list that contains pairs of points for a window's form using C#. The list size will change depending on the data that is loaded.
A simplified version of my approach, to simply convey the problem, is as follows (in the real app, the for-loops will iterate over sizes dependent on loaded data):
int[,] dummyInt = new int[1, 2];
List<int[,]> test = new List<int[,]>();
for (int i = 0; i < 100; i++)
{
dummyInt[0, 0] = i;
for (int j = 0; j < 5; j++)
{
dummyInt[0, 1] = j;
test.Add(dummyInt);
}
}
//Show the values in the list for debugging
foreach (int[,] value in test)
{
MessageBox.Show(value.ToString("G"));
}
Using this approach, all 500 values in the list are [99,4].
What I was expecting/hoping to get was
value 1 [0,0]
value 2 [0,1]
...
value 500 [99,4]
Seems like the list is storing the actual variable, and then changing the value with every iteration of the for loop. How can I store just the value of dummyInt as a new object to the list?
I searched for this, but I'm not sure I know the appropriate vocabulary to nail down the search.
Your List object is storing reference to the dummyInt object. If you want to store different values in List you have to create new int array every time you are adding it to List.
Reference:
https://msdn.microsoft.com/en-gb/library/4d43ts61(v=vs.90).aspx
Firstly, you don't need a 2-dimensional array if you're just storing a pair of coordinates. The first coordinate can go in the first element of a 1-dimensional array, and the second coordinate can go in the second element of the array. Secondly, the Clone method can be used to make a copy of an array object if you want to force a separate copy of the whole array to exist.
int[] dummyInt = new int[2];
List<int[]> test = new List<int[]>();
for (int i = 0; i < 100; i++)
{
dummyInt[0] = i;
for (int j = 0; j < 5; j++)
{
dummyInt[1] = j;
test.Add((int[])dummyInt.Clone());
}
}
foreach (int[] value in test)
{
Console.WriteLine("({0},{1})", value[0], value[1]);
}
And finally, an array might not be the best way to store a pair of coordinates. You might want to use a tuple or make your own structure. If you use a Value type (struct) instead of a Reference type (class), you don't need to clone each one.
struct Pair
{
public int x;
public int y;
}
public class Test
{
public static void Main()
{
Pair dummyInt = new Pair();
List<Pair> test = new List<Pair>();
for (int i = 0; i < 100; i++)
{
dummyInt.x = i;
for (int j = 0; j < 5; j++)
{
dummyInt.y = j;
test.Add(dummyInt);
}
}
foreach (Pair value in test)
{
Console.WriteLine("({0},{1})", value.x, value.y);
}
}
}
Note how the result is different if you change the word struct at the beginning to class.
is there a way to force a method in c# to accept arrays/variables of different types in the same signature slot or to make it ignore one part of the signature?
My code:
private void array_joiner(String[,] newArray, Int32[,] MatrixArray, String[,] RekursionArray, Char[] ArrayX, Char[] ArrayY)
{
for (Int16 i = 0; i < ArrayX.Length + 1; i++)
{
newArray[i, 0] = ArrayX[i].ToString();
}
for (Int16 i = 1; i < ArrayY.Length + 1; i++)
{
newArray[0, i] = ArrayY[i].ToString();
}
for (Int16 y = 1; y < ArrayY.Length + 1; y++)
{
for (Int16 x = 1; x < ArrayX.Length +1; x++)
{
newArray[y, x] = MatrixArray[y, x].ToString();
}
}
}
My problem is basically that I want to parse two different arrays in the slot of Int32[,]MatrixArray (Int32[,] and String[,]) to the method but I just don't know how. Anyone got a better idea than to write two different methods? Thx in advance.
You could just declare them as the Array class and then work out the type of the data in the arrays and how many ranks they have separately.
You basically have two ways:
Make it a generics method http://msdn.microsoft.com/it-it/library/512aeb7t.aspx (being careful to handle multidimensional collections which could be tricky)
Overload the method, declaring two signatures with the same name and different parameters http://msdn.microsoft.com/en-us/library/vstudio/ms229029(v=vs.100).aspx
I cannot get a listbox of years 1913-2013 using a for loop to work. This is the code I have so far..
lstYear.Items.Clear();
int[] year;
year = new int[100];
for (int y = 100; y > 1913; y++)
{
year[y] = y + 1;
lstYear.Items.Add(year[y]);
}
to add a list of DateTime objects from 1/1/1913 to 1/1/2013:
lstYear.Items.AddRange(Enumerable.Range(1913,101)
.Select(x => new DateTime(x,1,1)));
to add a list of ints from 1913 to 2013:
lstYear.Items.AddRange(Enumerable.Range(1913,101));
This loop:
for (int y = 100; y > 1913; y++)
{
year[y] = y + 1;
lstYear.Items.Add(year[y]);
}
Will never actually execute, since 100 is not greater than 1913. In a for loop, the loop will continue until the expression in the middle evaluates to false. You probably want:
for (int y = 0; y < 100; y++)
{
year[y] = y + 1913; // Start at 1913
lstYear.Items.Add(year[y]);
}
Also, I must ask, is there a need for the array at all? Why not just add the numbers directly into lstYear.Items? I'd probably write this as:
for (int y = 1913; y < 2014; y++)
{
lstYear.Items.Add(y.ToString()); // Not sure if .ToString is needed, but I think .Add() takes a string
}
Since you are new here is the structure you want.
You can also do it using a range, but that's out of question.
This question is how to populate using a "For" loop.
In your for loop you are starting at 100
for (int y = 1913; y <= 2013; y++)
lstYear.Items.Add(y);
Hello Everyone
What I am trying to do is call the "FillDeck" method to fill the "deck []" with 52 array elements. The for loop is used to add the elements - for testing purposes it is just adding the y+x values from the for loop.
What I did was use the variable "placement" to indicate my index position then increment the placement variable so for each loop iteration the index is increased thus adding an array element to that particular index. However, I get the IndexOutOfRangeException which is what I trying to figure out.
To note: I CANNOT automatically use predetermined values for the array, I must call a method which purpose is to add the values to the array. Since it is a card deck having a nested for loop to determine the rank / suit would be a good way to approach this.
Thanks =)
static void Main(string[] args)
{
int [] deck = {};
FillDeck(deck); // Error Here
}
public static void FillDeck(int[] deck)
{
int placement = 0;
// 0 = Ace , 12 = King : 0 = Hearts, 1 = Diamonds, 2 = Clubs, 3 = Spades
for (int x = 0; x < 13; x++)
for (int y = 0; x < 4; ++y)
{
deck[placement] = x + y;// Error here
++placement;
}
}
int [] deck = {}
This creates an array of size 0.
You can't put anything in it.
You need to write new int[52] (or other appropriate number) to create an array that can actually hold things.
Alternatively, you can create a List<T>, which can expand to any (reasonable) size by calling the Add() method.
Of course error there, array inited size is 0 means no element you can store in it.
hope code below can help you:
public static int[] FillDeck()
{
var deck = new List<int>();
// 0 = Ace , 12 = King : 0 = Hearts, 1 = Diamonds, 2 = Clubs, 3 = Spades
for (int x = 0; x < 13; x++)
for (int y = 0; x < 4; ++y)
{
deck.Add(x + y);
}
return deck.ToArray();
}
I have matrix with 3 dimension (n*m*k). I am trying to fined the maximum number for each n and m by searching in k dimension.((I try to find the maximum number in k dimension for each n and m)) and at last i have a 2d matrix (n*m). i have the following code but it is so slow. Is there any new code or any changes to the current code that do this more quickly.
thanks.
my c# code: note: li is the 3 dimension matrix and they are grater or equal to zero.
int[,] array2 = new int[n, m];
int[,] array = new int[n, m];
List<Array> li = new List<Array>();
for(int k = 0; k <'not a specific value, change each time' ; k++)
{
li.Add(array);
%% changing array
} %% so li will became a (n*m*k) matrix
for (int i = 0; i < n; i++)
for (int j = 0; j < m; j++)
{
int ma = -2;
int d = 0;
while (d <= k)
{
ma = Math.Max(ma, Convert.ToInt32(li[d].GetValue(i, j)));
d++;
}
array2[i, j] = ma;
}
The biggest performance issue is that you use Array objects as elements of your list. This makes it so that every element access using GetValue boxes the value, i.e. allocates a new tiny object to hold the element value.
Your code will run a lot faster if you replace
List<Array> li = new List<Array>();
with
List<int[,]> li = new List<int[,]>();
and
ma = Math.Max(ma, Convert.ToInt32(li[d].GetValue(i, j)));
with
ma = Math.Max(ma, li[d][i, j];
Since you don't know the 3rd dimension in advance, it is harder to use 3D arrays.
An entirely different approach would be to compute the maximum as you're building the list li. This will help in two ways: 1. You avoid indexing into the list of arrays and 2. as long as m and n aren't too large, you improve locality. That is: the values you're working with are closer together in memory, and more likely to be in the processor cache.
This should do the trick (even though it could be kinda slower than your approach):
// put this at the top of your source file
using System.Linq;
// put this where you calculate the maxima
for(int i = 0; i < array2.GetLength(0); ++i)
for(int j = 0; j < array2.GetLength(1); ++j)
{
array2[i, j] = Convert.ToInt32(li.Max(x => x.GetValue(i, j)));
}
You could use a three-dimensional array like this:
int xRange = 10;
int yRange = 10;
int zRange = 10;
int[, ,] matrix = new int[xRange, yRange, zRange];
// set up some dummy values
for (int x = 0; x < xRange; x++)
for (int y = 0; y < yRange; y++)
for (int z = 0; z < zRange; z++)
matrix[x, y, z] = x * y * z;
// calculate maximum values
int[,] maxValues = new int[xRange, yRange];
/* LINQ version of maximum calculation
for (int x = 0; x < xRange; x++)
for (int y = 0; y < yRange; y++)
maxValues[x, y] = Enumerable.Range(0, zRange).Select(z => matrix[x, y, z]).Max();
*/
// longhand version of maximum calculation
for (int x = 0; x < xRange; x++)
for (int y = 0; y < yRange; y++)
for (int z = 0; z < zRange; z++)
maxValues[x, y] = Math.Max(maxValues[x, y], matrix[x, y, z]);
// display results
for (int x = 0; x < xRange; x++)
{
for (int y = 0; y < yRange; y++)
Console.Write("{0}\t", maxValues[x, y]);
Console.WriteLine();
}
From an algorithm perspective, there's no more efficient way to evaluate the maximum value for fixed n,m for all k. It will take O(n*m*k) operations.
Now, the only way to improve performance is to find improvements in your implementation, particularly in your storage of the 3D matrix.
Using List<Array> is a major area for improvement. You are prone to boxing issues (conversion of primitive types to objects) and making more function calls than are necessary.
Reduce your 3D matrix to an array of primitives:
int[] my3DArray = new int[n * m * l]; // Note I'm using l where you use k
Now index into your array at [i, j, k] using the following offset:
int elementAtIJK = my3DArray[i + (n * j) + (m * n * k)];
If you just use arrays of primitives you should see a definite improvement.
Edit:
In fact, in C# (and several other languages) it's very easy to implement 3D arrays directly, e.g.:
int[,,] my3DArray = new int[n,m,l];
int elementAtIJK = my3DArray[i,j,k];
Which is much simpler than I first described (but at the end of the day is internally translated in the 1D form).
What to do if the 3rd dimension varies in size...
Now, it gets more interesting if the size of the 3rd dimension varies significantly. If it has a known maximum and isn't too big, you can simply set it to the maximum and fill the empty values with zeroes. This is simple and may meet your needs.
However, if the 3rd dimension can be very big, all these extra stored zeroes could waste a lot of valuable space and what you need is a Sparse Matrix representation.
There are different storage mechanisms for sparse matrices. For your purposes, you could consider your 3D array to be a 2D matrix, with (n*m) rows and max(k) columns. As the 3rd dimension varies in length, there are lots of empty spaces in your columns. This is called a sparse row and the standard data storage for this is "Compressed Sparse Row". Again, for performance this can be represented just by three primitive arrays, a data array, a row index array and a column pointer array. There are resources elsewhere on the web that describe the CSR implementation better than I can, but hopefully this will point you in the right direction.