Initializing two dimensional array of objects - c#

I have a 2-dimensional array of objects, which I initialize using the traditional loop:
PairDS[,] tempPb1 = new PairDS[LoopCounterMaxValue+1, LoopCounterMaxValue+1];
for (int i = 0; i <= LoopCounterMaxValue; i++)
for (int j = 0; j <= LoopCounterMaxValue; j++)
tempPb1[i, j] = new PairDS();
Is there any better way to do this using Enumerable or something?

I thought Initialize could do it, but it only works with value types.
int N = 10;
PairDS[,] temp = new PairDS[N + 1, N + 1];
temp.Initialize();
What I recommend you do is use a jagged array.
class PairDS { public PairDS(int row, int col) { } }
static void Main(string[] args)
{
int N = 10;
PairDS[][] temp = Enumerable.Range(0, N + 1).Select(
(row) => Enumerable.Range(0, N + 1).Select(
(col) => new PairDS(row, col)).ToArray()).ToArray();
}

I don't believe you can represent a multi-dimensional array as an Enumerable or List, directly because it (the CLR) has no way of knowing how you intend to index the array.
If you did work it out row by row, it'd actually be worse (ie slower) then simply looping through the array as you're doing and initializing each cell.

There's no way to directly initialize a 2D array with the Enumerable types and as some users have pointed out there's nothing directly wrong with what you're doing. If you're just looking to simplify the loop though this might be what you're looking for;
const int length = LoopCounterMaxValue + 1;
PairDS[,] tempPb1 = new PairDS[length, lenth];
for (var i = 0; i < length * length; i++) {
var column = i % length;
var row = (i - column) / length;
tempPb1[row, column] = new PairDS();
}

Related

Trying to find Frequency of elements in array

I am trying to count how many times a number appears in an array 1 (a1) and then trying to print out that number by storing it in array 2 (a2) just once and then try to print array 2. But first using for loop and a function, I will check that if a number already exist in array 2 then move to next index in array 1, unfortunateley this code is not working; can someone please help me in trying to fix it, I don't need some complex solutions like dictionaries or lists athe moment, although it might be helpful too. thanks, I am not an expert in programming and I try to practise it in my free time, so please help me.
I just want this code to be fixed for my understanding and knowledge
class Program
{
static void Main(string[] args)
{
int i, j;
int[] a1 = new int[10];
int[] a2 = new int[10];
int[] a3 = new int[10];
//takes an input
for (i = 0; i < a1.Length; i++)
{
a1[i] = Convert.ToInt32(Console.ReadLine());
}
for (i = 0; i < a1.Length; i++)
{
Cn(a1, a2); //calls in function
i++; //increments is if true
int count = 0;
for (j = 0; j < a1.Length; j++)
{
//if a number matches with a number in second array
if (a1[i] == a1[j])
{
//do count ++
count++;
// store that number into second array
a2[i] = a1[i];
}
}
//store the number of counts in third array
a3[i] = count;
}
for (i = 0; i < a2.Length; i++)
{
if (a2[i] != 0)
{
Console.WriteLine(a2[i]);
}
}
Console.ReadLine();
}
//function to check if element at current index of array 1 exists in array 2 if yes than break
public static void Cn (int[] aa1, int [] aa2)
{
int k, j;
for ( k = 0; k < aa1.Length; k++)
{
for (j = 0; j < aa2.Length; j++)
{
if (aa1[k] == aa2[j])
break;
}
}
}
}
You probably want to do a group by count:
int[] a1 = new int[10];
var rnd = new Random();
//takes an input
for (int i = 0; i < a1.Length; i++)
{
a1[i] = Convert.ToInt32(rnd.Next(0, 11)); // or Console.ReadLine()
}
var grouped = a1
.GroupBy(x => x)
.Select(g => new
{
Item = g.Key,
Count = g.Count()
}).ToList(); // ToList() is optional, materializes the IEnumerable
foreach (var item in grouped)
{
Console.WriteLine($"number: {item.Item}, count: {item.Count}");
}
This uses a Hash algorithm internally.
You can solve this without a Hash or Dictionary but it wouldn't be very efficient because you need to do lots of linear searches through the arrays.
The advantage of a Hash algorithm is that your lookups or groupings are much faster than if you loop over a complete array to find / increment an item.

Save the sum of each row of a matrix into an array

I have a matrix and I want to return an array containing as elements the sum of each row elements of the matrix.
int [] sum;
for (var i = 0; i < m; i++)
{
for (var j = 0; j < result.Pages[i].Actual.Count; j++)
{
sum[i] += result.Pages[i].Actual[j];
}
}
This is how I tried to do it but seems it is not working. Any ideas?
Use var m = a.GetLength(0); to get number of rows, and var n = a.GetLength(1); to get number of columns.
now that looks like a different story after you edit:
Actually the first problem would be a NullreferenceException because int[]sum is not initialized!
Anyway, so it seems that you have an array of arrays. In this case you would need the Length of the Pages array to save your results. The first loop iterates over it using i and will run until result.Pages.Length. For each i you have correctly implemented a second loop where you sum up the result.
int [] sum = new int[result.Pages.Length];
for (var i = 0; i < result.Pages.Length; i++)
{
for (var j = 0; j < result.Pages[i].Actual.Length; j++)
{
sum[i] += result.Pages[i].Actual[j];
}
}
If you collections are List's then you need to use Count instead of Length
The Linq solution would look like this:
int [] sum = result.Pages.Select(x=>x.Sum()).ToArray();
EDIT:
double? means that you have a nullable data type. This is different from the normal double. Furthermore the default value will be null That means that you need to initialize the value at position i in sum before you add up values, otherwise the result will be null.
double? [] sum = new double?[result.Pages.Length];
for (var i = 0; i < result.Pages.Length; i++)
{
sum[i] = 0;
for (var j = 0; j < result.Pages[i].Actual.Length; j++)
{
sum[i] += result.Pages[i].Actual[j];
}
}

C#:How can I compare between the sum of every row in 2D array?

I would like to know how can I check if the sum of every row in 2D array is equal to each other.
Edit: I tired the way Mike suggested but i still got the index out of range. What am I missing?
bool sumSame;
int sum3=0;
int sum4 = 0;
for (int i = 0; i < arr.GetLength(0); i++)
{
sum3 += arr[0, i];
}
for (int i = 0; i < arr.GetLength(0); i++)
{
sum4 = 0;
for (int j = 0; j < arr.GetLength(1); i++)
{
**sum4 += arr[i, j];**//The Error is Here
}
if (sum4 != sum3)
{
sumSame = false;
break;
}
}
sumSame = true
You would like to know if all rows in a 2D array have the same sum.
So, you need to write a function which computes the sum of a row.
Then your problem becomes one-dimensional: check whether a function invoked for every element of a one-dimensional array returns the same value for each element. (The fact that an element is in turn another array is irrelevant.)
If you do not want to (or do not know how to) write a function, then you can write the code which computes the sum of a row as a nested loop, (as you already tried to do,) but still, it helps if you conceptually treat these two tasks as completely different from each other, meaning that they should not mix their variables, and the outer loop should only use the result of the calculation of the inner loop.
Generally, the way we make sure that all elements of an array are equal to a certain value is that we compute the value of the first element, (at index 0,) and then we loop for each subsequent element (for( int i = 1; ...) and check whether the value computed for this element is equal to the value that we got for the first element.
You can add the sum of each array to the List<int> and check the number of distinct results with Distinct().Count(), if it's 1 the results are the same for all 2D array.
int[,] arr = new int[,]
{
{1,2,3 },
{3,2,1 },
{2,3,1 }
};
List<int> sums = new List<int>();
for (int i = 0; i < arr.GetLength(0); i++)
{
int sum = 0;
for (int j = 0; j < arr.GetLength(1); j++)
{
sum += arr[i, j];
}
sums.Add(sum);
}
bool sameResults = sums.Distinct().Count() == 1;

Convert 2D float array into 1D array of strings

I have a 2D array of floats and I want to convert it into 1D array of strings, where each string is one row of elements from 2D array. I am not getting output in text file as I expected. Can anyone tell me what I'm doing wrong? It will be great help to me, if somebody could provide efficient code with corrections.
string[] set = new string[240];
string value = "#"
for (int i = 0; i < 240; i++)
{
for (int j = 0; j < 320; j++)
{
value = Convert.ToString(ImageArray[i, j]);
value += ",";
}
set[i] = value + Environment.NewLine;
value = " ";
}
for(int k=0;k<240;k++)
{
System.IO.File.AppendAllText(#"C:\Users\mtech\Desktop\sathya.txt", set[k]);
textBlock1.Text = set[k];
value = " ";
}
inside your inner for loop(j), you are overwriting the value of value variable.
i.e.
for (int j = 0; j < 320; j++)
{
value = Convert.ToString(ImageArray[i, j]);
value += ",";
}
instead of above, you should be doing:
for (int j = 0; j < 320; j++)
{
value += Convert.ToString(ImageArray[i, j]) +",";
}
also, you don't need to perform two nested loops for this task, take a look at String.Join
Here is the shorter way with LINQ:
var allValues = ImageArray.OfType<float>();
string[] lines = new string[240];
for(int i=0; i<240; i++)
{
lines[i] = string.Join(",", allValues.Skip(i*320).Take(320));
}
File.AppendAllLines(#"C:\Users\mtech\Desktop\sathya.txt", lines);
You're re-assigning value in every iteration in your nested for loop. Use the += operator, instead. Another thing you should consider is the use of StringBuilder if you're going to repeatedly append to a string. strings are immutable so you're actually creating a new string every time you append to it.
Not sure if this applies to your case (because of the boundaries in your for loops), but you can use LINQ to flatten a multidimensional array. Example:
float[,] arr = new float[2,2]
{
{123.48F, 45.3F},
{954.23F, 91.3F}
};
var str = string.Join("",
arr.Cast<float>()
.Select(x => Convert.ToString(x) + ","));

2D Array. Set all values to specific value

To assign specific value to 1D array I'm using LINQ like so:
int[] nums = new int[20];
nums = (from i in nums select 1).ToArray<int>();
nums[0] = 2;
There is similar way to do so in 2D ([x,y]) array?
Or short way, without using nested loops?
If you really want to avoid nested loops you can use just one loop:
int[,] nums = new int[x,y];
for (int i=0;i<x*y;i++) nums[i%x,i/x]=n;
You can make it easier by throwing it into some function in a utility class:
public static T[,] GetNew2DArray<T>(int x, int y, T initialValue)
{
T[,] nums = new T[x, y];
for (int i = 0; i < x * y; i++) nums[i % x, i / x] = initialValue;
return nums;
}
And use it like this:
int[,] nums = GetNew2DArray(5, 20, 1);
LINQ doesn't work particularly well with multi-dimensional arrays.
Jagged arrays aren't too bad:
var array = Enumerable.Range(0, 10)
.Select(x => Enumerable.Repeat('x', 10).ToArray())
.ToArray();
... but rectangular arrays don't have any specific support. Just use loops.
(Note the use of Enumerable.Repeat as a somewhat simpler approach to creating the 1-dimensional array, btw.)
Well, this might be cheating because it simply moves the looping code to an extension method, but it does allow you to initialize your 2D array to a single value simply, and in a fashion similar to how you can initialize a 1D array to a single value.
First, as Jon Skeet mentioned, you could clean up your example of initializing a 1D array like this:
int [] numbers = Enumerable.Repeat(1,20).ToArray();
With my extension method, you will be able to initialize a 2D array like this:
public static T[,] To2DArray<T>(this IEnumerable<T> items, int rows, int columns)
{
var matrix = new T[rows, columns];
int row = 0;
int column = 0;
foreach (T item in items)
{
matrix[row, column] = item;
++column;
if (column == columns)
{
++row;
column = 0;
}
}
return matrix;
}
One way you could do this is like so:
// Define a little function that just returns an IEnumerable with the given value
static IEnumerable<int> Fill(int value)
{
while (true) yield return value;
}
// Start with a 1 dimensional array and then for each element create a new array 10 long with the value of 2 in
var ar = new int[20].Select(a => Fill(2).Take(10).ToArray()).ToArray();
May I suggest a new extension method.
public static class TwoDArrayExtensions
{
public static void ClearTo(this int[,] a, int val)
{
for (int i=a.GetLowerBound(0); i <= a.GetUpperBound(0); i++)
{
for (int j=a.GetLowerBound(1); j <= a.GetUpperBound(1); j++)
{
a[i,j] = val;
}
}
}
}
Use it like this:
var nums = new int[10, 10];
nums.ClearTo(1);
You can create a simple method that loops over all elements and initializes them:
public static void Fill2DArray<T>(T[,] arr, T value)
{
int numRows = arr.GetLength(0);
int numCols = arr.GetLength(1);
for (int i = 0; i < numRows; ++i)
{
for (int j = 0; j < numCols; ++j)
{
arr[i, j] = value;
}
}
}
This uses the same syntax as Array.Fill and will work for an array of any type

Categories

Resources