Multi-Dim Array to 1D - getting it to work with protobuf - c#

Protobuf doesn't support multi-dim arrays so I decided to use this implementation to make a 1D array out of a 2D one.
I get a Cannot cast from source type to destination type in the ToProtoArray method when I call the MultiLoop function. Any ideas on how to fix this?
public static ProtoArray<T> ToProtoArray<T>(this System.Array array)
{
// Copy dimensions (to be used for reconstruction).
var dims = new int[array.Rank];
for (int i = 0; i < array.Rank; i++) dims[i] = array.GetLength(i);
// Copy the underlying data.
var data = new T[array.Length];
var k = 0;
array.MultiLoop(indices => data[k++] = (T)array.GetValue(indices));
// ^^^^^^^^^^ cannot cast from source type to destination type
return new ProtoArray<T> { Dimensions = dims, Data = data };
}
public static System.Array ToArray<T>(this ProtoArray<T> protoArray)
{
// Initialize array dynamically.
var result = System.Array.CreateInstance(typeof(T), protoArray.Dimensions);
// Copy the underlying data.
var k = 0;
result.MultiLoop(indices => result.SetValue(protoArray.Data[k++], indices));
return result;
}
public static void MultiLoop(this System.Array array, System.Action<int[]> action)
{
array.RecursiveLoop(0, new int[array.Rank], action);
}
private static void RecursiveLoop(this System.Array array, int level, int[] indices, System.Action<int[]> action)
{
if (level == array.Rank)
{
action(indices);
}
else
{
for (indices[level] = 0; indices[level] < array.GetLength(level); indices[level]++)
{
RecursiveLoop(array, level + 1, indices, action);
}
}
}
[ProtoContract]
public class ProtoArray<T>
{
[ProtoMember(1)]
public int[] Dimensions { get; set; }
[ProtoMember(2)]
public T[] Data { get; set; }
}
Here's how I use this to serialize a 2D array:
[ProtoContract]
public class Tile
{
[ProtoMember(1)]
public int x;
[ProtoMember(2)]
public int y;
// ...
}
Tile[,] map; // meanwhile I assign the data to the array
map1d = Extensions.ToProtoArray<Tile[,]>(map);
using (var file = File.Create(path))
{
Serializer.Serialize(file, map1d);
}

I think this is what you need:
public class ProtoArray<T>
{
public ProtoArray(T[] array)
{
this.Data=array;
this.Dimensions=new int[array.Length];
}
public ProtoArray(T[,] array)
{
int n = array.GetLength(0);
int m = array.GetLength(1);
this.Data=new T[n*m];
for(int i = 0; i<n; i++)
{
for(int j = 0; j<m; j++)
{
// Row Major
Data[i*m+j]=array[i, j];
// For Column Major use Data[i+j*n]=array[i, j];
}
}
this.Dimensions=new[] { n, m };
}
public int[] Dimensions { get; set; }
public T[] Data { get; set; }
public T[] ToArray()
{
if(Dimensions.Length==1)
{
return Data.Clone() as T[];
}
else
{
throw new NotSupportedException();
}
}
public T[,] ToArray2()
{
if(Dimensions.Length==2)
{
int n = Dimensions[0], m = Dimensions[1];
T[,] array = new T[n, m];
for(int i = 0; i<n; i++)
{
for(int j = 0; j<m; j++)
{
array[i, j]=Data[i*m+j];
}
}
return array;
}
else
{
throw new NotSupportedException();
}
}
}
public class Tile
{
public int x;
public int y;
// ...
}
class Program
{
static void Main(string[] args)
{
Tile[,] map = new Tile[16, 4];
ProtoArray<Tile> array = new ProtoArray<Tile>(map);
//serialize array
//
// de-serialize array
Tile[,] serialized_map = array.ToArray2();
}
}

Related

sorting a generic list from within a generic container class

I need to sort a list by any one of its properties, but i dont know which of these properties it will specifically be sorted on. The Main method below.
static void Main(string[] args)
{
Things<Something> something = new Things<Something>();
something.Add(new Something
{ Thing = "Apartment", Price = 1500000 });
something.Add(new Something
{ Thing = "Bed", Price = 10000 });
something.Add(new Something
{ Thing = "Lamp", Price = 600 });
something.Add(new Something
{ Thing = "Car", Price = 5000000 });
Console.WriteLine("\n\tStuff sorted by description");
something = something.SelectionSort("Thing");
foreach (Something thing in something)
Console.WriteLine("\t" + thing);
Console.WriteLine("\n\tStock items sorted by value");
something = something.SelectionSort("Value");
foreach (Something thing in something)
Console.WriteLine("\t" + thing);
Console.Write("\n\tPress any key to exit ...");
Console.ReadKey();
}
I have a struct
public struct Something
{
public string Thing { get; set; }
public decimal Price { get; set; }
}
And a generic container class called things
public class Things<T> : IEnumerable<T>
{
private List<T> lstItems;
public int Count { get { return lstItems.Count; } }
public Things() { lstItems = new List<T>(); }
public Things(List<T> items_) { lstItems = new List<T>(items_); }
public void Add(T item)
{
lstItems.Add(item);
}
public T this[int i]
{
get { return lstItems[i]; }
set { lstItems[i] = value; }
}
IEnumerator IEnumerable.GetEnumerator()
{
throw new System.NotImplementedException();
}
public IEnumerator<T> GetEnumerator()
{
foreach (T item in lstItems)
yield return item;
}
}
An extensions class extends the generic container class
public static class ExtensionsClass
{
private static string SortFiield { get; set; }
private static object GetProperty<T>(T thing, string nameofProp)
{
return thing.GetType().GetProperty(nameofProp).GetValue(thing, null);
}
private static int Compare<T>(T x, T y)
{
IComparable propX = (IComparable)GetProperty(x, SortFiield);
IComparable propY = (IComparable)GetProperty(y, SortFiield);
return propX.CompareTo(propY);
}
public static Things<T> SelectionSort<T>(this Things<T> things, string SORTFIELD)
{
List<T> lsstt = new List<T>(things);
int iIndex;
T temporary;
SortFiield = SORTFIELD;
for (int i = 0; i < lsstt.Count - 1; i++)
{
iIndex = i;
for (int j = i + 1; j < lsstt.Count; j++)
{
string first = GetProperty(lsstt[j], SortFiield).ToString();
string second = GetProperty(lsstt[iIndex], SortFiield).ToString();
if (Compare(first, second) < 0)
iIndex = j;
}
temporary = lsstt[i];
lsstt[i] = lsstt[iIndex];
lsstt[iIndex] = temporary;
}
return new Things<T>(lsstt);
}
}
The problem i am encountering is that get property in the extension class returns null, but i know that the object i am trying to return exists. It is found by the "String first = ...." line but when getproperty is called from the Compare method then it returns null.
You are passing "first", "second" to Compare. In your case both of them are strings and not objects, you need to pass "lsstt[j]" and "lsstt[iIndex]" to it.
if (Compare(lsstt[j], lsstt[iIndex]) < 0)
iIndex = j;

Array index out of bounds in Array with arbitrary index bounds

I Wrote a class which allows users to set a bottom bound of array, in instance "myArray(-5, 10)" where -5 start index and 10 length of array. But I am getting an error when I compare i <= myArray.GetArrayLength. What I did wrong. I will appriciated any help.
using System;
namespace UsArrClass
{
class Program
{
class UserArr
{
private int[] _UsArr;
private int _start;
private int _len;
public int[] UsArr
{
get => this._UsArr;
set => this._UsArr = value;
}
public int BotomBoundary
{
get => this._start;
set => this._start = value;
}
public int TopBoundary => (GetUserArrLength -1) + BotomBoundary;
public int GetUserArrLength => _len;
public UserArr(int start, int len)
{
this.BotomBoundary = start;
this._len = len;
UsArr = new int [len];
}
public int this[int n]
{
get => UsArr[n - BotomBoundary];
set => UsArr[n - BotomBoundary] = value;
}
static void Main(string[] args)
{
UserArr myarr = new UserArr( 0, 3);
for (int i = myarr.BotomBoundary; i <= myarr.GetUserArrLength; i++)
{
myarr[i] = i;
Console.Write(" "+ myarr[i]);
}
Console.WriteLine();
Console.WriteLine(myarr.TopBoundary);
Console.WriteLine(myarr[1]);
Console.WriteLine(myarr.BotomBoundary);
Console.WriteLine(myarr.GetUserArrLength);
}
}
}
}

How to take union of an array by using operator overloading?

I take a class Set A class that will keep an array in the constructor of class we initialize the array and make two objects of that array and like
I need that at + operator the union of two array should come
guide me .and at operator parameter a and b it is giving error also
public class seta
{
public seta(int size)
{
this.size = Size;
int[] array = new int[size]
}
private int size;
public int Size
{
get { return size; }
set { size = value; }
}
Console.WriteLine ("enter size of an array aray");`
`
int a = Convert.ToInt32(Console.ReadLine());
seta obja = new seta(a);
Console.WriteLine("enter size of an array aray");
int b = Convert.ToInt32(Console.ReadLine());
seta objb = new seta(b);
}
public static double operator + ( a , b )
{
}
This code will create two random arrays stored in class SetA { } and then find the union with the operator +. Under the hood it just calls Enumerable.Union()
public class SetA
{
static Random rng = new Random();
int[] data;
public SetA(int[] data)
{
this.data=data;
}
public SetA(int size)
{
this.data=new int[size];
for (int i = 0; i<data.Length; i++)
{
data[i]=rng.Next(0, 100);
}
}
public int Size { get { return data.Length; } }
public int[] Data { get { return data; } }
public static SetA operator +(SetA a, SetA b)
{
return new SetA(a.data.Union(b.data).ToArray());
}
}
class Program
{
static void Main(string[] args)
{
SetA a = new SetA(100);
SetA b = new SetA(50);
SetA c = a+b;
int n = c.Size;
}
}

Insert, display, min and max in array list in C#

I'm new in C#. I have this program and I need to add the function for insert, function min, function max, and function display.
namespace unSortedArrayAssignment
{
class unSortedArray
{
public int size;
public int[] array;
//Constructor for an empty unsorted array
public unSortedArray(int MAX_SIZE)
{
array = new int[MAX_SIZE]; //Create a C# array of size MAX_SIZE
size = 0; // Set size of unSortedArray to 0
}
//Append assuming array is not full
public void Append(int value)
{
array[size] = value;
size++;
}
//Remove the last item
public void Remove()
{
if (size != 0)
size--;
}
//Search for an item
public int Search(int value)
{
for (int counter = 0; counter < size; counter++)
{
if (array[counter] == value)
return counter;
}
return -1;
}
//Delete an item
public void Delete(int value)
{
int index = Search(value);
if (index != 0)
{
for (int counter = index; counter < size; counter++)
array[counter] = array[counter + 1];
size--;
}
}
}
}
class unSortedArray
{
public int size;
public int[] array;
public unSortedArray()
{
array = new int[int size here];
}
public int Min()
{
return array.Min();
}
public int Max()
{
return array.Max();
}
public void Insert(int value)
{
Array.Resize<int>(ref array, array.Count() + 1);
array[array.Count() - 1] = value;
}
}

how to use variables of a class from other classes in c#

i need to call variables that are defined in a class
class testclasss
{
public testclass(double[,] values)
{
double[][] rawData = new double[10][];
for (int i = 0; i < 10; i++)
{
rawData[i] = new double[] { values[i, 2], stockvalues[i, 0] }; // if data won't fit into memory, stream through external storage
}
int num = 3;
int max = 30;
}
public int[] checkvalue(double[][] rawData, int num, int maxCount)
{
............
}
}
I have called constructor using
testclass newk = new testclass(values);
now how can i call the function checkvalues(). i tried using newk.num,newk.maxcount but those variables were not recognized.
Just as your class constructor and checkvalues function are public, so too must the properties you wish to access from outside the class. Put these at the top of your class declaration:
public int num {get; set;}
public int max {get; set;}
Then you can access them via newk.num and newk.max.
EDIT: In response to your second comment, I think you might be a bit confused about how functions and properties interact within the same class. This might help:
class TestClass {
private int _num;
private int _max;
private double[][] _rawData;
public TestClass(double[,] values, int num, int max)
{
_num = num;
_max = max;
_rawData = new double[10][];
for (int i = 0; i < 10; i++)
{
_rawData[i] = new double[] { values[i, 2], stockvalues[i, 0] };
}
}
public int[] CheckValues()
{
//Because _num _max and _rawData exist in TestClass, CheckValues() can access them.
//There's no need to pass them into the function - it already knows about them.
//Do some calculations on _num, _max, _rawData.
return Something;
}
}
Then, do this (for example, I don't know what numbers you're actually using):
double[,] values = new double[10,10];
int num = 3;
int max = 30;
Testclass foo = new Testclass(values, num, max);
int[] results = foo.CheckValues();
I believe this is what you're looking for:
class TestClass {
public int num { get; set; }
public int max { get; set; }
public double[][] rawData;
public TestClass(double[,] values)
{
rawData = new double[10][];
for (int i = 0; i < 10; i++)
{
rawData[i] = new double[] { values[i, 2], stockvalues[i, 0] }; // if data won't fit into memory, stream through external storage
}
this.num = 3;
this.max = 30;
}
public int[] CheckValue()
{............}
}
You'll need a property with a get accessor.
Here is a simplified example based on your code:
class testclass
{
private int _num = 0;
private int _max = 0;
public int Num
{
set { _num = value; }
get { return _num; }
}
public int Max
{
set { _max = value; }
get { return _max; }
}
public testclass()
{
Num = 3;
Max = 30;
}
}
//To access Num or Max from a different class:
testclass test = new testclass(null);
Console.WriteLine(test.Num);
Hope that helps.
Using your exact same code, except for public testclass(double[,] values), which I changed to public testfunction(double[,] values)
class testclass
{
public testfunction(double[,] values)
{
double[][] rawData = new double[10][];
for (int i = 0; i < 10; i++)
{
rawData[i] = new double[] { values[i, 2], stockvalues[i, 0] }; // if data won't fit into memory, stream through external storage
}
int num = 3;
int max = 30;
}
public int[] checkvalue(double[][] rawData, int num, int maxCount)
{
............
}
}
Have you tried calling checkvalues() function like this?
testclass.checkvalue();

Categories