Merging multiple Arrays with reference - c#

I want to be able to have multiple arrays and be able to merge them together. This concept is easy, but I also want to be able to change one of the original arrays and have the merged array change as well. The idea is that some sort of reference system would be built effectively making the merged array an array of pointers.
Example Code:
int[] a1 = new int[5];
int[] a2 = new int[5];
for (int i = 0; i < 5; i++)
{
a1[i] = i;
a2[i] = i + 5;
}
int[] a3;
a3 = MergeFunction(a1, a2)
Console.WriteLine(a3[0] + "");
a1[0] = 10;
Console.WriteLine(a3[0] + "");
Console.ReadKey();
This would output first 0, then 10

you can use Linq to solve this. For example
void Main()
{
int[] a1 = new int[5];
int[] a2 = new int[5];
for (int i = 0; i < 5; i++)
{
a1[i] = i;
a2[i] = i + 5;
}
IEnumerable<int> a3;
a3 = MergeFunction(a1, a2);
Console.WriteLine(a3.ToArray()[0] + "");
a1[0] = 10;
Console.WriteLine(a3.ToArray()[0] + "");
Console.ReadKey();
}
public IEnumerable<int> MergeFunction(int[] a1, int[] a2)
{
return a1.Union(a2);
}
Because of the deferred execution of linq it shows also the changes in the base arrays.
With this in mind you can write a small class to make the syntax for item access similar to the array syntax for item access. For example:
void Main()
{
int[] a1 = new int[5];
int[] a2 = new int[5];
for (int i = 0; i < 5; i++)
{
a1[i] = i;
a2[i] = i + 5;
}
ArrayMerger<int> a3 = new ArrayMerger<int>(a1,a2);
Console.WriteLine(a3[0] + "");
a1[0] = 10;
Console.WriteLine(a3[0] + "");
a2[0] = 15;
Console.WriteLine(a3[5] + "");
}
public class ArrayMerger<T>
{
private readonly IEnumerable<T> arrayUnion;
public ArrayMerger(T[] array1, T[] array2)
{
arrayUnion = array1.Union(array2);
}
public T this[int i]
{
get
{
return arrayUnion.ElementAt(i);
}
}
}

I think there's no reference system you are looking for. You have to do the merging everytime when there's a change made to the original array.

In my case, I didn't actually want to use ints but another class that I had made so for the sample code, I will be using an arbitrary Class, but if someone else wants to use an int, go to this page and look at solutions for value variables.
C#: Array of references / pointers to a number of integers
Firstly, I made a very simple variable class
public class Variable
{
public int a;
public int b;
public int c;
public Variable(int a, int b, int c)
{
this.a = a;
this.b = b;
this.c = c;
}
}
Finally, here is the code to test the reference idea
static void Main(string[] args)
{
//definition of variables
Variable[] a1 = new Variable[5];
Variable[] a2 = new Variable[5];
//fill the variables
for (int i = 0; i < 5; i++)
{
a1[i] = new Variable(i, i* 2, i*3);
a2[i] = new Variable(i + 5, (i+ 5) * 2, (i+5) * 3);
}
//define combination
Variable[] a3;
//join arrays
a3 = a1.Union(a2).ToArray();
//inefficient print
Console.WriteLine(a3[0].a + "");
//change original array
a1[0].a = 10;
//inefficient print
Console.WriteLine(a3[0].a + "");
Console.ReadKey();
}
This outputs 0 then 10

Related

C#, Trying to pull prime numbers from generated array all I get is 0

The program will generate a sequence of randomly chosen numbers between 1 – 100. The sequence will consist of 20 elements.
Your program should display the sequence once it is generated.
Then, it will display all prime numbers within this sequence.
The code so far:
class Program
{
int[] rnum = new int[100];
int[] selecting = new int[20];
static void Main(string[] args)
{
Program myProgram = new Program();
myProgram.Numbers();
myProgram.PrimeN();
Console.ReadLine();
}
public void Numbers()
{
int[] rnum = new int[100];
// Filling the array with values 1 to 100:
for (int i = 0; i < rnum.Length; i++)
{
rnum[i] = i + 1;
}
// Shuffling the elements of the array:
Random rnd = new Random();
for (int i = 0; i < rnum.Length; i++)
{
int j = rnd.Next(i, rnum.Length);
int temp = rnum[i];
rnum[i] = rnum[j];
rnum[j] = temp;
}
// Selecting and presenting 20 numbers:
int[] selecting = new int[20];
for (int i = 0; i < 20; i++)
selecting[i] = rnum[i];
selecting.ToList().ForEach(i => Console.Write(i.ToString() + ", "));
Console.WriteLine();
}
public void PrimeN()
{
List<int> primeNumbers = new List<int>();
for (int i = 0; i < selecting.Length; i++)
{
if (IsPrime(selecting[i]))
{
primeNumbers.Add(selecting[i]);
}
}
Console.Write("Non-Prime Numbers:");
for (int i = 0; i < primeNumbers.Count; i++)
{
Console.Write(primeNumbers[i] + " ");
}
}
bool IsPrime(int number)
{
for (int i = 2; i < Math.Sqrt(number); i++)
{
if (number % i == 0) return false;
}
return true;
}
}
}
You created local variable called selecting inside Numbers() function. Scope of this local variable is within Numbers() function.
When you are trying to read same variable in PrimeN(), it is referring to the globally defined selecting variable.
As there is nothing stored in global selecting variable you are getting 0 as result in primeNumbers array.
To Solve this issue, do not create local variable called selecting inside Numbers() function, use globally defined variable i.e. selecting defined at class level
...
public void Numbers()
{
...
// Selecting and presenting 20 numbers:
//COMMENT BELOW LINE
//int[] selecting = new int[20];
for (int i = 0; i < 20; i++)
selecting[i] = rnum[i]; //This will refer member which is defined globally
selecting.ToList().ForEach(i => Console.Write(i.ToString() + ", "));
Console.WriteLine();
}
The first problem I see, is you are creating local variables, instead of using the instance members you have declared, after your method runs, nothing gets changed... it all happened locally in the method.
Comment out the below lines, you have already declared them
public static void Numbers(int size)
{
//int[] rnum = new int[size];
...
//int[] selecting = new int[20];
Though it could all be reduced to
private static readonly Random _r = new Random();
static void Main(string[] args)
{
var numbers = Generate(100);
var selected = numbers.Take(20).ToArray();
Console.WriteLine("Selected : " + string.Join(", ", selected));
Console.Write("Primes : " + string.Join(",", selected.Where(IsPrime)));
Console.ReadLine();
}
public static int[] Generate(int size)
{
var numbers = Enumerable.Range(1, 100).ToArray();
// Shuffling the elements of the array:
for (var i = 0; i < numbers.Length; i++)
{
var j = _r.Next(i, numbers.Length);
var temp = numbers[i];
numbers[i] = numbers[j];
numbers[j] = temp;
}
return numbers;
}
private static bool IsPrime(int number)
{
for (var i = 2; i < Math.Sqrt(number); i++)
if (number % i == 0) return false;
return true;
}
Output
Selected : 92, 79, 1, 44, 83, 48, 70, 49, 80, 19, 27, 65, 50, 40, 20, 10, 68, 25, 9, 28
Primes : 79,1,83,49,19,25,9

List.Add function adds reference to the object or adds its value in the list

I have a program to print all possible combinations from a string array. The printing is done fine on the screen. However, When I add the same to a list, all list members reflect the last generated combination. So, I am not sure what is happening. Please see the code below.
class Program
{
static List<string[]> list = new List<string[]>();
static void combinationUtil(string[] arr, string[] data,
int start, int end,
int index, int r)
{
// Current combination is
// ready to be printed,
// print it
if (index == r)
{
list.Add(data);
for (int j = 0; j < r; j++)
{
Console.Write(data[j] + " ");
}
Console.WriteLine("");
return;
}
// replace index with all
// possible elements. The
// condition "end-i+1 >=
// r-index" makes sure that
// including one element
// at index will make a
// combination with remaining
// elements at remaining positions
for (int i = start; i <= end &&
end - i + 1 >= r - index; i++)
{
data[index] = arr[i];
combinationUtil(arr, data, i + 1,
end, index + 1, r);
}
}
// The main function that prints
// all combinations of size r
// in arr[] of size n. This
// function mainly uses combinationUtil()
static void printCombination(string[] arr,
int n, int r)
{
// A temporary array to store
// all combination one by one
string[] data = new string[r];
// Print all combination
// using temprary array 'data[]'
combinationUtil(arr, data, 0,
n - 1, 0, r);
}
// Driver Code
static public void Main()
{
string[] arr = { "string-1", "string-2", "string-3", "string-4" };
int r = 2;
int n = arr.Length;
printCombination(arr, n, r);
foreach (var item in list)
{
Console.WriteLine(item[0]+" "+item[1]);
}
}
}
Following is the output
I found a way to do this. But, I am not sure if this is the only and best way to do this. If you have any other way of doing this better, please answer. Following is how I did this.
list.Add(new string[2] { data[0], data[1] });
Here is a solution using List. Note the string[] uniquePair = new string[2]; prior to each list.Add().
class Program
{
static List<string[]> list = new List<string[]>();
// Driver Code
static public void Main()
{
string[] arr = { "string-1", "string-2", "string-3", "string-4" };
int r = 2;
for (int i = 0; i < arr.Length; i++)
{
for (int j = i + 1; j < arr.Length; j++)
{
string[] uniquePair = new string[2];
uniquePair[0] = arr[i];
uniquePair[1] = arr[j];
list.Add(uniquePair);
}
}
foreach (string[] pair in list)
{
Console.WriteLine($"{ pair[0] } + { pair[1] }");
}
Console.ReadKey(true);
}
}
Output:
string-1 + string-2
string-1 + string-3
string-1 + string-4
string-2 + string-3
string-2 + string-4
string-3 + string-4

How to test bounds of a bidimensional array, to avoid indexOutOfRangeException (C#)

It's pretty simple to deal with an array with one dimension. But how can we avoid testing out of range locations within a bi dimensional array with different lengths on each row (jagged array)?
here is my code (if anyone wants to test):
static void Main(string[] args)
{
object[][] x = weirdReturn();
int k = 0;
while(x[0][k] != null) //THIS CODE PRODUCES THE EXCEPTION
{
for(int i = 0; i< x[k].Length; i++)
{
Console.Write("{0} ", x[k][i]);
}
Console.WriteLine("");
k++;
}
}
static object[][] weirdReturn()
{
DateTime d = new DateTime();
d = DateTime.Now;
object[] a2 = { 'X', 1.79, d, 100 };
object[] a1 = { 0, 'a', "objectX" };
object[][] retVal = new object[2][];
retVal[0] = a1;
retVal[1] = a2;
return retVal;
}
There is no magic to this - simply check the length and avoid indexing beyond that value minus one, as you would with a one-dimensional array.
Your code looks pretty messy, are you just trying to loop over the arrays like this?
static void Main(string[] args)
{
object[][] x = weirdReturn();
for (int i = 0; i < x.Length; i++)
{
for (int j = 0; j < x[i].Length; j++)
{
Console.Write("{0} ", x[i][j]);
}
Console.WriteLine("");
}
}
static object[][] weirdReturn()
{
DateTime d = new DateTime();
d = DateTime.Now;
object[] a2 = { 'X', 1.79, d, 100 };
object[] a1 = { 0, 'a', "objectX" };
object[][] retVal = new object[2][];
retVal[0] = a1;
retVal[1] = a2;
return retVal;
}

Null Reference Excepetion when trying to assign value to two dimensional array

Hi I have an assignment in which I need to resolve a system of linear equations using Gausian elimination method.
This is my code so far:
private static double[][] equation = new double[][]
{
new double[] {0.0, 8.0, 2.0, -7.0},
new double[] {3.0, 5.0, 2.0, 8.0},
new double[] {6.0, 2.0, 8.0, 26.0}
};
private const int rowSize = 3;
private const int columnSize = 4;
private static int pivotRow;
private static int curentRowIndex;
public static void GetTriangularMatrix()
public static void GetTriangularMatrix()
{
PrintMatrix();
for (int k = 0; k <= columnSize - 2; k++)
{
curentRowIndex = k;
double pivot = GetPivot(k);
SwapCurentRowWithPivotRow(pivot);
FindTriangularMatrix();
}
}
public static double GetPivot(int curentPivot)
{
double pivot = equation[curentPivot][curentPivot];
pivotRow = curentPivot;
for (int i = curentPivot; i <= rowSize - 1; i++)
{
if (pivot < equation[i][curentPivot])
{
pivot = equation[i][curentPivot];
pivotRow = i;
}
}
Console.WriteLine("Pivot Row is " + (pivotRow + 1));
Console.WriteLine("Pivot is " + pivot);
return pivot;
}
private static void SwapCurentRowWithPivotRow(double pivot)
{
if(pivot != equation[curentRowIndex][curentRowIndex])
{
double temp;
for (int i = 0; i <= columnSize - 1; i++)
{
temp = equation[curentRowIndex][i];
equation[curentRowIndex][i] = equation[pivotRow][i];
equation[pivotRow][i] = temp;
}
}
PrintMatrix();
}
public static void FindTriangularMatrix()
{
double[][] trangularMatrix = new double[rowSize][];
for (int j = curentRowIndex + 1; j <= rowSize - 1; j++)
{
trangularMatrix[j][curentRowIndex] = equation[j][curentRowIndex] / equation[curentRowIndex][curentRowIndex];
}
}
At FindTriangularMatrix() method when I try to assign some value to the triangularMatrix I get back a null reference exception.
I believe this is more of a syntax problem , it may be something I am missing because I have never worked with two dimensional arrays before.
Can anyone tell me what I am doing wrong and how can I correct it?

Generic initialization of multidimensional array

I have a multidimensional array, which I want to initialize in a simple and fast way:
double[,,] arr = new double[4,5,6];
// doesn't work by design
foreach(double d in arr)
d = ... ; // my initialization value
This obviously doesn't works. But I would like to have a generic function for setting all array values to a choosen default. With own classes, I could write a special constructor, but with value types I've no real idea. With C++, I could access all items in a linear way with one for loop, but in C# I think I've to use as much for loops as I have dimensions. I've no better solution at the moment ( or I'm using unsafe code and pointer arithmetics, which would probably work.).
Is there a more elegant way for doing this ?
Not quite sure if it's what you want, but the following extension method will allow you to initialise every value in an array, regardless of the number of dimensions.
public static class ArrayExtensions
{
public static void Set<T>(this Array array, T defaultValue)
{
int[] indicies = new int[array.Rank];
SetDimension<T>(array, indicies, 0, defaultValue);
}
private static void SetDimension<T>(Array array, int[] indicies, int dimension, T defaultValue)
{
for (int i = 0; i <= array.GetUpperBound(dimension); i++)
{
indicies[dimension] = i;
if (dimension < array.Rank - 1)
SetDimension<T>(array, indicies, dimension + 1, defaultValue);
else
array.SetValue(defaultValue, indicies);
}
}
}
Use like so:
int[, ,] test1 = new int[3, 4, 5];
test1.Set(1);
int[,] test2 = new int[3, 4];
test2.Set(1);
int[] test3 = new int[3];
test3.Set(1);
I would strongly recommend using a 1D array, and map the values sequentially. You will need to convert from indeces i, j, k, ... into the proper array index, which is done with the Que() function below, part of a generic array class SeqArray<T>.
// Test code first
class Program
{
static void Main(string[] args)
{
/* 3 pages, of a 4x2 matrix
*
* |16 17|
* | 8 9|19|
* | 0 1|11|21|
* | 2 3|13|23|
* | 4 5|15|
* | 6 7|
*
* shown above are the sequential indeces for a rank 3 array
*/
SeqArray<double> arr = new SeqArray<double>(3, 4, 2);
// Initialize values to squential index "num"
int num = 0;
for (int i = 0; i < 3; i++)
{
for (int j = 0; j < 4; j++)
{
for (int k = 0; k < 2; k++)
{
arr[i, j, k] = num++;
}
}
}
// Check that the array values correspond to the index sequence
num = 0;
for (int i = 0; i < 3 * 4 * 2; i++)
{
Trace.Assert(arr.InnerArray[i] == num++);
}
// Initialize with value=π
arr = new SeqArray<double>(Math.PI, 4, 5, 6);
}
}
public class SeqArray<T>
{
T[] values;
int[] lengths;
public SeqArray(params int[] lengths)
{
this.lengths = lengths;
int N = 1;
for (int i = 0; i < lengths.Length; i++)
{
N *= lengths[i];
}
values = new T[N];
}
public SeqArray(T value, params int[] lengths) : this(lengths)
{
for (int i = 0; i < values.Length; i++)
{
values[i] = value;
}
}
public int[] Lengths { get { return lengths; } }
public int Size { get { return values.Length; } }
internal T[] InnerArray { get { return values; } }
public int Que(params int[] indeces)
{
// Check if indeces are omited like arr[4] instead of arr[4,0,0]
if (indeces.Length < lengths.Length)
{
// Make a new index array padded with zeros
int[] temp = new int[lengths.Length];
indeces.CopyTo(temp, 0);
indeces = temp;
}
// Count the elements for indeces
int k = 0;
for (int i = 0; i < indeces.Length; i++)
{
k = lengths[i] * k + indeces[i];
}
return k;
}
public T this[params int[] indeces]
{
get { return values[Que(indeces)]; }
set { values[Que(indeces)] = value; }
}
}
Here is a non-recursive version alternative to that posted by Andy Holt above:
public static void SetAll<T>(this Array array, T value)
{
var sizes = new int[array.Rank];
sizes[array.Rank - 1] = 1;
for (var d = array.Rank - 2; d >= 0; d--)
{
sizes[d] = array.GetLength(d + 1)*sizes[d + 1];
}
for (var i = 0; i < array.Length; i++)
{
var remainder = i;
var index = new int[array.Rank];
for (var d = 0; d < array.Rank && remainder > 0; d++)
{
index[d] = remainder / sizes[d];
remainder -= index[d]*sizes[d];
}
array.SetValue(value, index);
}
}

Categories