C# Jagged arrays for loop implementation question - c#

I can't find how to implement jagged array using for loop. I have tried, however only the last smaller array becomes jagged arrays item.
string[][] allSheets = new string[size][];
This is how I declare. Below is how I get allSheets[number] element.
public string[] get_Sheets(int colNum)
{
CellReference[] cr = new CellReference[rows_.Length];
ISheet sheet = wb.GetSheetAt(0);
IRow[] row = new IRow[rows_.Length];
ICell[] cell = new ICell[rows_.Length];
string[] cellResult = new string[rows_.Length];
for (int i = 0; i < cr.Length; i++)
{
cr[i] = new CellReference(rows_[i] + colNum);
row[i] = sheet.GetRow(cr[i].Row);
cell[i] = row[i].GetCell(cr[i].Col);
cellResult[i] = cell[i].ToString();
}
return cellResult;
}
My two for loops looks something like this:
for (int ii = 0; ii < size; ii++)
{
for (int jj = 2; jj < size; jj++)
{
allSheets[ii] = get_Sheets(jj);
}
}
Notice how I started jj with 2. I had to since it's how excel files work..
You could clearly see that despite everything my every allSheets[ii] would become the last possible j number in for loop. I had tried to swap the loops so i starts first, however result is the same.

I think that you should use only one loop, because you are iterating only the main array here. You do not have to handle 2 dimensions on this level. The second loop (for the other dimension) is already inside get_Sheets.
for (int ii = 0; ii < size; ii++)
{
allSheets[ii] = get_Sheets(ii + 2);
}
Note that your 2 for-loops are not executing in parallel, they are nested. The inner loop is iterating size - 2 times per each iteration of the outer loop. This means that you are getting size * (size - 2) iterations. This not what you want.
An alternative way of doing this a lesser know feature of the for-loop. (This is probably what you intended to do with the 2 loops.)
for (int ii = 0, jj = 2; ii < size; ii++, jj++)
{
allSheets[ii] = get_Sheets(jj);
}

Related

Compare 2 tables and check if number exist

I have 2 tables with random numbers and i want to check which number from first table doesn't exist in second one and output it.
Example:
First table: 2, 6, 7, 9
Second table: 0, 6, 11, 3
Output: 2, 7, 9
My current code:
#region CompareTables
int[,] TABLE1 = new int[5, 10];
int[,] TABLE2 = new int[5, 10];
Random rnd = new Random();
for (int i = 0; i < 5; i++)
{
for (int j = 0; j < 10; j++)
{
TABLE1[i, j] = rnd.Next(1, 100);
TABLE2[i, j] = rnd.Next(1, 100);
}
}
Console.Write("TABLE1" + "\n\n");
for (int i = 0; i < 5; i++)
{
for (int j = 0; j < 10; j++)
Console.Write(TABLE1[i, j] + " " + "\t");
Console.WriteLine();
}
Console.Write("\n");
Console.Write("TABLE2" + "\n\n");
for (int i = 0; i < 5; i++)
{
for (int j = 0; j < 10; j++)
Console.Write(TABLE2[i, j] + " " + "\t");
Console.WriteLine();
}
for (int i = 0; i < 5; i++)
{
for (int j = 0; j < 10; j++)
if (TABLE1[i, j] == TABLE2[i, j])
Console.WriteLine();
}
Console.ReadKey();
#endregion
I would like to ask how to output numbers that are in first table but not in second?
The problem you are having is that your tables are 2 dimensional arrays and you are trying to index into them as if they were one dimensional arrays.
Look at how your are filling them up:
TABLE1[i, j] = rnd.Next(1, 100);
TABLE2[i, j] = rnd.Next(1, 100);
You are correctly using two indexes i and j (think of rows and columns).
However, later on you are doing:
if (TABLE1[1] == TABLE2[i]) //where is the second index?
This is obviously wrong, but instead of making this work, lets take a step back and think this through again. All this mucking around with two indexes seems a little... yeah, mucky, shouldn't there be a better way to do this?
In your current problem, the fact that the tables are multidimensional is simply a pain that doesn't really add any value. If you only need to return elements of the first table that are not present in the second table without any position information, then why all this hassle with indexes to begin with? Lets create a helper method that flattens the arrays and enables us to get rid of at least one index:
static IEnumerable<T> Flatten<T>(this T[,] array)
{
for (var i = 0; i < array.GetLength(0); i++)
for (var j = 0; j < array.GetLength(1); j++)
yield return array[i, j];
}
And now that we have one dimensional arrays (IEnumerable<T>s) we can leverage C#'s magic stick...LINQ! Solving your problem is as simple as:
var notPresent = TABLE1.Flatten().Except(TABLE2.Flatten());
But this can have horrible performance if the arrays are big enough. Remember how you would solve this problem by hand (and how Except does it too): take first element from table 1, check all elements from table 2 until you either find a match or there are no more elements. Take second element from table 1, check all elements from table 2 until... etc. That seems a lot of work, and it grows really fast if the tables are big. Also if your are not smart about it you might be doing unnecessary extra work because Table 1 and 2 might contain duplicate elements...
Can this be improved? Yes, there are specially built collections that allow really fast searches; Sets. In your case, a HashSet<int> seems like a pretty good choice.
Your code now would look like:
var set = new HashSet<int>(TABLE1.Flatten());
var notPresent = set.Except(TABLE2.Flatten());
And this will perform much better.
You could covert your 2D arrays into lists and find the numbers from TABLE1 that don't exist in TABLE2 with LINQ Except:
List<int> LIST1 = TABLE1.Cast<int>().ToList();
List<int> LIST2 = TABLE2.Cast<int>().ToList();
var result = LIST1.Except(LIST2);

How to build a large 2d array out of many smaller 2d arrays

I am trying to work towards a
512 x 512 (262144 elements)
I currently have a
List<double[,]> data;
Dimensions are:
4096 x [8 , 8] (262144 elements)
The 2d array I am working towards is square.
List<List<float>> newList = new List<List<float>(); //working towards
I have tried something along the lines of:
for (int i = 0; i < Math.Sqrt(data.Count); i++ ) {
List<float> row = new List<float>();
foreach (double[,] block in data) {
for (int j = 0; j < 8; j++) {
row.Add(block[i,j]); //i clearly out of range
}
}
newList.Add(row);
}
What I was trying to do there was to brute force my way and add up every row (which is 8 in length) and then add the large rows to the newList.
I believe you can do that in the following way
var newList = new List<List<float>>();
for (int i = 0; i < 512; i++)
{
var innerList = new List<float>();
for (int j = 0; j < 512; j++)
{
int x =(i/8)*64 + (j/8);
int y = i % 8;
int z = j % 8;
innerList.Add(data[x][y,z]);
}
newList.Add(innerList);
}
Basically you have 64x64 of your 8x8 blocks. So the (i,j) coordinate of the larger 512x512 structure translate in the following ways. First to determine the 8x8 block you have to figure out the row and column of the 64x64 structure of blocks by dividing the i and j by the size of the block (8) then you multiply the row (i/8) by the number of block in a row (64) and add the column (j/8). For the y and z it's simpler because you know that its just a matter of the remainder of i and j when divided by 8 (i%8) and (j%8).

Incrementing the values in an array

I am trying to separate a group of values into bins for a histogram chart. There will be 10 bins in my histogram. To sort and count the number of cases in each bin, I am using an array. The error I am getting is The operand of an increment or decrement operator must be a variable, property or indexer. idx will give me the bin number that needs to be incremented. I am just unsure of the proper way to increment it. Thank you for the suggestions and comments.
int binsize = Convert.ToInt32(xrLabel101.Text) / 10;//Max divided by 10 to get the size of each bin
this.xrChart4.Series[0].Points.Clear();
int binCount = 10;
for (int i = 0; i < binCount; i++)
{
int m = Convert.ToInt32(xrLabel104.Text);//This is the number of loops needed
string[] binct = new string[10];
for (int k = 0; k < m; k++)
{
int idx = Convert.ToInt32(currentcolumnvalue) / binsize;
binct[idx]++;//I know this is wrong. Suggestions?
}
}
This is a simple: the type returned by your expression binct[idx] does not support numerical
operation like ++, + -...
To avoid this there are at last a couple of ways:
Operator overloading
Execute the same operation on other type then this and map the result to type you want.
What you can do is:
int binsize = Convert.ToInt32(xrLabel101.Text) / 10;//Max divided by 10 to get the size of each bin
this.xrChart4.Series[0].Points.Clear();
int binCount = 10;
for (int i = 0; i < binCount; i++)
{
int m = Convert.ToInt32(xrLabel104.Text);//This is the number of loops needed
int[] binct = new int[10];
for (int k = 0; k < m; k++)
{
int idx = Convert.ToInt32(currentcolumnvalue) / binsize;
binct[idx] = binct[idx] + 1;
}
}
You're trying to increment a string which makes no sense. Make your array an array of int instead

filling multidimensional array with unique numbers in C#

I'm trying to write a code that will fill array with unique numbers.
I could write the code separately for 1, 2 and 3 dimensional arrays but number of for cycles grow to "infinity".
this is the code for 2D array:
static void fillArray(int[,] array)
{
Random rand = new Random();
for (int i = 0; i < array.GetLength(0); i++)
{
for (int j = 0; j < array.GetLength(1); j++)
{
array[i, j] = rand.Next(1, 100);
for (int k = 0; k < j; k++)
if (array[i, k] == array[i, j])
j--;
}
}
print_info(array);
}
Is it possible to do something like this for n-dimensional arrays?
My approach is to start with a 1-d array of unique numbers, which you can shuffle, and then slot into appropriate places in your real array.
Here is the main function:
private static void Initialize(Array array)
{
var rank = array.Rank;
var dimensionLengths = new List<int>();
var totalSize = 1;
int[] arrayIndices = new int[rank];
for (var dimension = 0; dimension < rank; dimension++)
{
var upperBound = array.GetLength(dimension);
dimensionLengths.Add(upperBound);
totalSize *= upperBound;
}
var singleArray = new int[totalSize];
for (int i = 0; i < totalSize; i++) singleArray[i] = i;
singleArray = Shuffle(singleArray);
for (var i = 0; i < singleArray.Length; i++)
{
var remainingIndex = i;
for (var dimension = array.Rank - 1; dimension >= 0; dimension--)
{
arrayIndices[dimension] = remainingIndex%dimensionLengths[dimension];
remainingIndex /= dimensionLengths[dimension];
}
// Now, set the appropriate cell in your real array:
array.SetValue(singleArray[i], arrayIndices);
}
}
The key in this example is the array.SetValue(value, params int[] indices) function. By building up the correct list of indices, you can use this function to set an arbitrary cell in your array.
Here is the Shuffle function:
private static int[] Shuffle(int[] singleArray)
{
var random = new Random();
for (int i = singleArray.Length; i > 1; i--)
{
// Pick random element to swap.
int j = random.Next(i); // 0 <= j <= i-1
// Swap.
int tmp = singleArray[j];
singleArray[j] = singleArray[i - 1];
singleArray[i - 1] = tmp;
}
return singleArray;
}
And finally a demonstration of it in use:
var array1 = new int[2,3,5];
Initialize(array1);
var array2 = new int[2,2,3,4];
Initialize(array2);
My strategy assigns sequential numbers to the original 1-d array to ensure uniqueness, but you can adopt a different strategy for this as you see fit.
You can use Rank property to get the total number of dimentions in your array
To insert use SetValue method
In the first two for loops you are analysing the array properly (i and j go from the start to the end of the corresponding dimension). The problem comes in the most internal part where you introduce a "correction" which actually provokes an endless loop for j.
First iteration:
- First loop: i = 0;
- Second loop: j = 0;
- Third loop: j = -1
Second iteration
- First loop: i = 0;
- Second loop: j = 0;
- Third loop: j = -1
. etc., etc.
(I start my analysis in the moment when the internal loop is used for the first time. Also bear in mind that the exact behaviour cannot be predicted as far as random numbers are involved. But the idea is that you are making the j counter back over and over by following an arbitrary rule).
What you want to accomplish exactly? What is this last correction (the one provoking the endless loop) meant to do?
If the only thing you intend to do is checking the previously stored values, you have to rely on a different variable (j2, for example) which will not affect any of the loops above:
int j2 = j;
for (int k = 0; k < j2; k++)
if (array[i, k] == array[i, j2])
j2--;

Find intersection group of sorted integer arrays

Let's we have some integer short sorted arrays and we need to find intersection equal or more then predefined constant.
Here is code and it demonstrates what i want to do better then i can explain it in words.
The problem is SPEED. My code is working very slow. It takes about 15 sec on 2000 elements array(on my slow machine). Ofcourse i can implement my own intersection method and parallize code but it give a very limited improvement. Execution time growing as N^2 or something and already for 500k arrays it takes a very very long time. So how can i rewrite algorithm for better perfomance? I am not limited c# language maybe CPU or GPU has good special instructions for such job.
Example:
Input:
1,3,7,8
2,3,8,10
3,10,11,12,13,14
minSupport = 1
Output:
1 and 2: 2, 8
1 and 3: 3
2 and 3: 3, 10
var minSupport = 2;
var random = new Random(DateTime.Now.Millisecond);
// Numbers is each array are unique
var sortedArrays = Enumerable.Range(0,2000)
.Select(x => Enumerable.Range(0,30).Select(t => random.Next(1000)).Distinct()
.ToList()).ToList();
var result = new List<int[]>();
var resultIntersection = new List<List<int>>();
foreach (var array in sortedArrays)
{
array.Sort();
}
var sw = Stopwatch.StartNew();
//****MAIN PART*****//
for (int i = 0; i < sortedArrays.Count-1; i++)
{
for (int j = i+1; j < sortedArrays.Count; j++)
{
var intersect = sortedArrays[i].Intersect(sortedArrays[j]).ToList();
if(intersect.Count()>=minSupport)
{
result.Add( new []{i,j});
resultIntersection.Add(intersect);
}
}
}
//*****************//
sw.Stop();
Console.WriteLine(sw.Elapsed);
EDIT:
Now it takes about 9 sec vs 15 sec with old algorithm on 2000 elements. Well...ofcourse it is not fast enough.
//****MAIN PART*****//
// This number(max value which array can contains) is known
var maxValue = 1000;
var reverseIndexDict = new Dictionary<int,List<int>>();
for (int i = 0; i < maxValue; i++)
{
reverseIndexDict[i] = new List<int>();
}
for (int i = 0; i < sortedArrays.Count; i++)
{
for (int j = 0; j < sortedArrays[i].Count; j++)
{
reverseIndexDict[sortedArrays[i][j]].Add(i);
}
}
var tempArr = new List<int>();
for (int i = 0; i < sortedArrays.Count; i++)
{
tempArr.Clear();
for (int j = 0; j < sortedArrays[i].Count; j++)
{
tempArr.AddRange(reverseIndexDict[j]);
}
result.AddRange(tempArr.GroupBy(x => x).Where(x => x.Count()>=minSupport).Select(x => new[]{i,x.Key}).ToList());
}
result = result.Where(x => x[0]!=x[1]).ToList();
for (int i = 0; i < result.Count; i++)
{
resultIntersection.Add(sortedArrays[result[i][0]].Intersect(sortedArrays[result[i][1]]).ToList());
}
//*****************//
EDIT:
Some improvent.
//****MAIN PART*****//
// This number(max value which array can contains) is known
var maxValue = 1000;
var reverseIndexDict = new List<int>[maxValue];
for (int i = 0; i < maxValue; i++)
{
reverseIndexDict[i] = new List<int>();
}
for (int i = 0; i < sortedArrays.Count; i++)
{
for (int j = 0; j < sortedArrays[i].Count; j++)
{
reverseIndexDict[sortedArrays[i][j]].Add(i);
}
}
for (int i = 0; i < sortedArrays.Count; i++)
{
var tempArr = new Dictionary<int, List<int>>();
for (int j = 0; j < sortedArrays[i].Count; j++)
{
var sortedArraysij = sortedArrays[i][j];
for (int k = 0; k < reverseIndexDict[sortedArraysij].Count; k++)
{
if(!tempArr.ContainsKey(reverseIndexDict[sortedArraysij][k]))
{
tempArr[reverseIndexDict[sortedArraysij][k]] = new[]{sortedArraysij}.ToList();
}
else
{
tempArr[reverseIndexDict[sortedArraysij][k]].Add(sortedArrays[i][j]);
}
}
}
for (int j = 0; j < reverseIndexDict.Length; j++)
{
if(reverseIndexDict[j].Count>=minSupport)
{
result.Add(new[]{i,j});
resultIntersection.Add(reverseIndexDict[j]);
}
}
}
// and here we are filtering collections
//*****************//
There are two solutions:
Let us suppose you have 3 sorted arrays and you have to find the intersection between them. Traverse the first array and run a binary search on the rest of the two arrays for the element in first array. If the respective binary search on two list gave positive, then increment the counter of intersection.
result = List
for element in Array1:
status1 = binarySearch(element, Array2)
status2 = binarySearch(element, Array2)
status = status & status
if status == True:
count++
if count == MAX_INTERSECTION:
result.append(element)
break
Time Complexity : N * M * Log(N),
where,
N = Number of element in the array
M = Number of arrays
This solution works only if the number in the arrays are positive integers. Calculate the maximum and the minimum number out of the total elements in all the sorted arrays. As it is sorted, we can determine it by surveying the start and end element of the sorted arrays given. Let the greatest number be max and the lowest number be min. Create an array of size max - min and fill it with zero. Let us suppose you have 3 Arrays, now start traversing the first array and and go to the respective index and increment the value in the previously created array. As mentioned below:
element is 5 in Array 1, the New_array[5]+=1
Traverse all the three sorted list and perform the operation mentioned above. At the end traverse the new_array and look for value equal to 3, these indexes are the intersection result.
Time Complexity : O(N) + O(N) + .. = O(N)
Space Complexity : O(maximum_element - minimum_element)
where,
N = number of elements in the array.

Categories