Serialization and deserialization of an int matrix c# - c#

I'm using a c# WCF service and I need to return a int[,] to the client in one of my method. The problem is multidimensional arrays are not supported by WCF so I think my only option is returning a byte array in this way:
public byte[] DistanceMatrix()
{
int[,] matrix;
//DOING THINGS HERE
IFormatter formatter = new BinaryFormatter();
var ms = new MemoryStream();
formatter.Serialize(ms, matrix);
return ms.ToArray();
}
But I don't know how to deserialize the byte[] back to an int[,].

This excellent blog post by Josh Reuben can help you:
Extension methods that will allow you to convert prior to serialization and convert back after deserialization:
public static T[,] ToMultiD<T>(this T[][] jArray)
{
int i = jArray.Count();
int j = jArray.Select(x => x.Count()).Aggregate(0, (current, c) => (current > c) ? current : c);
var mArray = new T[i, j];
for (int ii = 0; ii < i; ii++)
{
for (int jj = 0; jj < j; jj++)
{
mArray[ii, jj] = jArray[ii][jj];
}
}
return mArray;
}
public static T[][] ToJagged<T>(this T[,] mArray)
{
var cols = mArray.GetLength(0);
var rows = mArray.GetLength(1);
var jArray = new T[cols][];
for (int i = 0; i < cols; i++)
{
jArray[i] = new T[rows];
for (int j = 0; j < rows; j++)
{
jArray[i][j] = mArray[i, j];
}
}
return jArray;
}

Related

Convert object containing 2D object array into string array

I have a method which returns the following type and object:
object {object[,]}
test {object[19, 2]}
Is it possible to convert this into 2d string array, or a datatable?
Looks akward, but I haven't found another way.
int firstDimensionSize = 19;
int secondDimensionSize = 2;
object[,] objectArray = new object[firstDimensionSize, secondDimensionSize];
string[,] stringArray = new string[objectArray.Length / secondDimensionSize, secondDimensionSize];
for (int i = 0; i < objectArray.Length / secondDimensionSize; i++)
{
for (int j = 0; j < secondDimensionSize; j++)
{
stringArray[i, j] = objectArray[i, j].ToString();
}
}
In case your second dimension is always the same you could leave out the inner loop, replacing it with static code.
See also https://www.dotnetperls.com/2d
I made this extension method, but you can aswell make it a normal method if you don't need it that often.
public static class Extensions
{
public static string[,] ConvertToString2D(this object[,] arr)
{
int dim1 = arr.GetLength(0);
int dim2 = arr.GetLength(1);
string[,] strArray = new string[dim1, dim2];
for (int i = 0; i < dim1; i++)
{
for (int j = 0; j < dim2; j++)
{
strArray[i, j] = Convert.ToString(arr[i, j]);
}
}
return strArray;
}
}
and then you can call it like this:
var result = objArr.ConvertToString2D();

Remove Nulls from string[,]

I have a string array defined in c# as
string[,] options = new string[100,3];
Throughout the code it gets populated with data but not always filled.
So if I have 80 parts of it filled and 20 parts of it not filled. The 20 parts have nulls in them or 60 nulls at the end. Is there an easy way to resize the array so that after filling it the array is the same as
String[,] options = new string[80,3];
It would have to be resized based on the position of the first set of 3 nulls it found.
If this was a jagged array I would have done
options = options.Where(x => x != null).ToArray();
The method is quite long, because it has to check every row twice...
public static string[,] RemoveEmptyRows(string[,] strs)
{
int length1 = strs.GetLength(0);
int length2 = strs.GetLength(1);
// First we count the non-emtpy rows
int nonEmpty = 0;
for (int i = 0; i < length1; i++)
{
for (int j = 0; j < length2; j++)
{
if (strs[i, j] != null)
{
nonEmpty++;
break;
}
}
}
// Then we create an array of the right size
string[,] strs2 = new string[nonEmpty, length2];
for (int i1 = 0, i2 = 0; i2 < nonEmpty; i1++)
{
for (int j = 0; j < length2; j++)
{
if (strs[i1, j] != null)
{
// If the i1 row is not empty, we copy it
for (int k = 0; k < length2; k++)
{
strs2[i2, k] = strs[i1, k];
}
i2++;
break;
}
}
}
return strs2;
}
Use it like:
string[,] options = new string[100, 3];
options[1, 0] = "Foo";
options[3, 1] = "Bar";
options[90, 2] = "fiz";
options = RemoveEmptyRows(options);
As suggested by Alexei, there is another way of doing this:
public static string[,] RemoveEmptyRows2(string[,] strs)
{
int length1 = strs.GetLength(0);
int length2 = strs.GetLength(1);
// First we put somewhere a list of the indexes of the non-emtpy rows
var nonEmpty = new List<int>();
for (int i = 0; i < length1; i++)
{
for (int j = 0; j < length2; j++)
{
if (strs[i, j] != null)
{
nonEmpty.Add(i);
break;
}
}
}
// Then we create an array of the right size
string[,] strs2 = new string[nonEmpty.Count, length2];
// And we copy the rows from strs to strs2, using the nonEmpty
// list of indexes
for (int i1 = 0; i1 < nonEmpty.Count; i1++)
{
int i2 = nonEmpty[i1];
for (int j = 0; j < length2; j++)
{
strs2[i1, j] = strs[i2, j];
}
}
return strs2;
}
This one, in the tradeoff memory vs time, chooses time. It is probably faster, because it doesn't have to check every row twice, but it uses more memory, because it puts somewhere a list of the non-empty indexes.
I went for all rows until you find an row with all null values:
Needs some clean up and will obviously remove non-null rows that occur after the first all null row. The requirement wasn't too clear here
EDIT: Just seen the comment clarifying requirement to remove all null rows - I've tweaked the below to avoid downvotes but a more comprehensive answer is already accepted (and is more efficient) :)
void Main()
{
string[,] options = new string[100,3];
options[0,0] = "bleb";
options[1,1] = "bleb";
options[2,0] = "bleb";
options[2,1] = "bleb";
options[3,2] = "bleb";
options[4,1] = "bleb";
string[,] trimmed = TrimNullRows(options);
Console.WriteLine(trimmed);
}
public string[,] TrimNullRows(string[,] options)
{
IList<string[]> nonNullRows = new List<string[]>();
for (int x = 0; x < options.GetLength(0); x++)
{
bool allNull = true;
var row = new string[options.GetLength(1)];
for (int y = 0; y < options.GetLength(1); y++)
{
row[y] = options[x,y];
allNull &= options[x,y] == null;
}
if (!allNull)
{
nonNullRows.Add(row);
}
}
var optionsTrimmed = new string[nonNullRows.Count, options.GetLength(1)];
for (int i=0;i<nonNullRows.Count;i++)
{
for (int j=0;j<options.GetLength(1);j++)
{
optionsTrimmed[i, j] = nonNullRows[i][j];
}
}
return optionsTrimmed;
}
You can also get yourself some helpers to convert between jagged and multi-dimensional representations. This is pretty silly, of course, but for arrays as small as the ones you're showing (and also, very sparse arrays), it'll be fine.
void Main()
{
string[,] options = new string[100,3];
options[3, 1] = "Hi";
options[5, 0] = "Dan";
var results =
options
.JagIt()
.Where(i => i.Any(j => j != null))
.UnjagIt();
results.Dump();
}
static class Extensions
{
public static IEnumerable<IEnumerable<T>> JagIt<T>(this T[,] array)
{
for (var i = 0; i < array.GetLength(0); i++)
yield return GetRow(array, i);
}
public static IEnumerable<T> GetRow<T>(this T[,] array, int rowIndex)
{
for (var j = 0; j < array.GetLength(1); j++)
yield return array[rowIndex, j];
}
public static T[,] UnjagIt<T>(this IEnumerable<IEnumerable<T>> jagged)
{
var rows = jagged.Count();
if (rows == 0) return new T[0, 0];
var columns = jagged.Max(i => i.Count());
var array = new T[rows, columns];
var row = 0;
var column = 0;
foreach (var r in jagged)
{
column = 0;
foreach (var c in r)
{
array[row, column++] = c;
}
row++;
}
return array;
}
}
The JagIt method is pretty simple of course - we'll just iterate over the rows, and yield the individual items. This gives us an enumerable of enumerables, which we can use in LINQ quite easily. If desired, you could transform those into arrays, of course (say, Select(i => i.ToArray()).ToArray()).
The UnjagIt method is a bit more talkative, because we need to create the target array with the correct dimensions first. And there's no unyield instruction to simplify that :D
This is pretty inefficient, of course, but that isn't necessarily a problem. You could save yourself some of the iterations by keeping the inner enumerable an array, for example - that will save us having to iterate over all the inner items.
I'm mostly keeping this as the memory-cheap, CPU-intensive alternative to #xanatos' memory-intensive, CPU-cheap (relatively).
Of course, the main bonus is that it can be used to treat any multi-dimensional arrays as jagged arrays, and convert them back again. General solutions usually aren't the most efficient :D
Yet another variant with linq
static string[,] RemoveNotNullRow(string[,] o)
{
var rowLen = o.GetLength(1);
var notNullRowIndex = (from oo in o.Cast<string>().Select((x, idx) => new { idx, x })
group oo.x by oo.idx / rowLen into g
where g.Any(f => f != null)
select g.Key).ToArray();
var res = new string[notNullRowIndex.Length, rowLen];
for (int i = 0; i < notNullRowIndex.Length; i++)
{
Array.Copy(o, notNullRowIndex[i] * rowLen, res, i * rowLen, rowLen);
}
return res;
}

Converting Codility solution to C# (Grocery-store, Hydrogenium 2013)

In order to learn and understand how Dijkstra's algorithm is used to solve the "Grocery Store" ([Hydrogenium 2013]: https://codility.com/programmers/challenges/hydrogenium2013) problem on codility, I'm trying to rewrite the #2, O(n^2) solution(https://codility.com/media/train/solution-grocery-store.pdf) in C#.
1) What language are those solutions written in?
2) What would be the C# equivalent to this bit of code?
G = [[]] *N
for i in xrange(M):
G[A[i]] = G[A[i]] + [(B[i], C[i])]
G[B[i]] = G[B[i]] + [(A[i], C[i])]
This is what I have so far
int[] G = new int[N];
for (int i = 0; i < M; i++)
{
G[A[i]] = G[A[i]];
G[B[i]] = G[B[i]];
}
Thanks in advance,
Gregory
Downloaded IDLE (a python IDE...kind of) and figured it out. It appears to be adding pairs to each array element. Here's the code I came up with if anyone else happens to stumble across the same problem.
private struct nodePair
{
public int node;
public int time;
public nodePair(int node, int time)
{
this.node = node;
this.time = time;
}
}
public int solution(int[] A, int[] B, int[] C, int[] D)
{
int M = A.Length;
int N = D.Length;
//build the graph
List<nodePair>[] G = new List<nodePair>[N];
for (int i = 0; i < N; i++)
{
G[i] = new List<nodePair>();
}
for (int i = 0; i < M; i++)
{
G[A[i]].Add(new nodePair(B[i], C[i]));
G[B[i]].Add(new nodePair(A[i], C[i]));
}
//initialize the distance table
int[] dist = new int[N];
for (int i = 0; i < N; i++)
{
dist[i] = int.MaxValue;
}
bool[] visited = new bool[N];
for (int i = 0; i < N; i++)
{
visited[i] = false;
}
//look for the minimum value
int ii = 0; ;
dist[0] = 0;
for (int k = 0; k < N; k++)
{
int s = int.MaxValue;
//find the minimum
for (int j = 0; j < N; j++)
{
if ((dist[j] < s) && (visited[j] == false))
{
s = dist[j];
ii = j;
}
}
visited[ii] = true;
if (s < D[ii])
{
return s;
}
List<nodePair> thisNodeLIst = G[ii];
foreach (nodePair oneNode in thisNodeLIst)
{
dist[oneNode.node] = Math.Min(dist[oneNode.node], s + oneNode.time);
}
}//for
return -1;
}
}

Is it possible to specialize generics

I'm having a generic Converter class
public class Converter
{
public static TargetType[] Convert<SourceType, TargetType>(SourceType[] data)
where SourceType : struct
where TargetType : struct
{
int N = data.Length;
TargetType[] result = new TargetType[N];
for (int i = 0; i < N; i++)
{
// We does this not work, what can I do else
result[i] = (TargetType)data[i];
}
return result;
}
}
Question 1: Why is is not possible to do the cast? What can I do else? Convert.ChangeType is to slow.
Because of slow performance in general I decided to do it in unsafe code. Unfortunately it's not possible to create pointers to generics - as it is widely known. For that reason I created a converter that decides the type at runtime and performs the casts with a lot of if's.
No one question came up. Can I create a generic Convert routine and specialize it in a way, that in some cases I have defined datatypes. I currently don't know how, but maybe I you read the example you get a clue:
public static double[] Convert<double, int>(int[] data)
{
int N = data.Length;
double[] result = new double[N];
unsafe
{
fixed (int* data_pinned = data)
fixed (double* out_pinned = result)
{
int* A = data_pinned;
double* B = out_pinned;
for (int i = 0; i < N; i++, A++, B++)
{
*B = ((double)*A);
}
}
}
return result;
}
Below you can find a "small" demo project which shows the performance values of different casts:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Diagnostics;
namespace ConsoleApplication1
{
public static class CastTest
{
public static unsafe double[] Cast1(int[] input)
{
int N = input.Length;
double[] output = new double[N];
for (int i = 0; i < N; i++) output[i] = (double)(input[i]);
return output;
}
public static unsafe double[] Cast2(int[] input)
{
int N = input.Length;
double[] output = new double[N];
fixed (double* output_pinned = output)
{
double* outp = output_pinned;
fixed (int* input_pinned = input)
{
int* inp = input_pinned;
for (int i = 0; i < N; i++, inp++, outp++) *outp = (double)(*inp);
}
return output;
}
}
public static unsafe double[] Cast3(int[] input)
{
int N = input.Length;
double[] output = new double[N];
fixed (double* output_pinned = output)
{
double* outp = output_pinned;
fixed (int* input_pinned = input)
{
int* inp = input_pinned;
for (int i = 0; i < N; i++) outp[i] = (double)(inp[i]);
}
return output;
}
}
public static unsafe double[] Cast4(int[] input)
{
int N = input.Length;
double[] output = new double[N];
fixed (double* output_pinned = output)
{
fixed (int* input_pinned = input)
{
for (int i = 0; i < N; i++) output_pinned[i] = (double)(input_pinned[i]);
}
}
return output;
}
public static unsafe double[] Cast5(int[] input)
{
double[] output = new double[input.Length];
for (int i = 0; i < input.Length; i++) output[i] = (input[i]);
return output;
}
public static unsafe double[] Cast6(int[] input)
{
Converter<int, double> converter = (A) =>
{
return A;
};
return Array.ConvertAll<int, double>(input, converter);
}
public static void StartTest()
{
int[] A = new int[100000];
int N = 10000;
var w1 = Stopwatch.StartNew();
for (int i = 0; i < N; i++) { double[] A1 = Cast1(A); }
w1.Stop();
Console.WriteLine(String.Format("{0}: {1}ms", 1, w1.ElapsedMilliseconds));
var w2 = Stopwatch.StartNew();
for (int i = 0; i < N; i++) { double[] A2 = Cast2(A); }
w2.Stop();
Console.WriteLine(String.Format("{0}: {1}ms", 2, w2.ElapsedMilliseconds ));
var w3 = Stopwatch.StartNew();
for (int i = 0; i < N; i++) { double[] A3 = Cast3(A); }
w3.Stop();
Console.WriteLine(String.Format("{0}: {1}ms", 3, w3.ElapsedMilliseconds));
var w4 = Stopwatch.StartNew();
for (int i = 0; i < N; i++) { double[] A4 = Cast4(A); }
w4.Stop();
Console.WriteLine(String.Format("{0}: {1}ms", 4, w4.ElapsedMilliseconds));
var w5 = Stopwatch.StartNew();
for (int i = 0; i < N; i++) { double[] A5 = Cast5(A); }
w5.Stop();
Console.WriteLine(String.Format("{0}: {1}ms", 5, w5.ElapsedMilliseconds));
var w6 = Stopwatch.StartNew();
for (int i = 0; i < N; i++) { double[] A6 = Cast6(A); }
w6.Stop();
Console.WriteLine(String.Format("{0}: {1}ms", 6, w6.ElapsedMilliseconds));
}
}
}
Any help is greatly appreciated to improve the performance.
The sizes for array size and repetitions are real values for me. In fact for testing purpose these values are also a little lower than normally used.
Is there a possibility to do this?
Thanks
Martin
It's not possible to do the cast because there's no guarantee that there is a conversion between the two types involved. What if SourceType is Guid and TargetType is double? The compiler basically can't emit a conversion.
The simplest approach is probably to provide a delegate:
public static TTarget[] Convert<TSource, TTarget>(TSource[] data,
Func<TSource, TTarget> conversion)
{
TargetType[] result = new TargetType[data.Length];
for (int i = 0; i < data.Length; i++)
{
result[i] = conversion(data[i]);
}
return result;
}
Of course this is basically the same as calling Array.ConvertAll... does that not do what you want?
Yes, there'll be a small performance overhead from calling the conversion frequently - but have you proved to yourself that that performance overhead is a problem? I would at least try using Array.ConvertAll as a first attempt.

Best way to convert int[][] to int**?

This is kind of a curiosity question. I do have an existing solution, but I wonder if people know of a better approach.
My callers want to call me with int[][]. I have a routine that needs to process an int**. What's the best way to do this conversion? In other words:
public static void Func1(int[][] data) {
Func2(data); //how to do this?
}
private unsafe static void Func2(int** data) {
//process data
}
Following is the best approach I could come up with. It works fine, but I can't say I'm 100% happy with the recursive approach (and the O(data.Length) stack space it requires)
public static void Main() {
var test=new[] {
new [] {10},
new [] {20,30},
new [] {40,50,60},
new [] {70,80,90,100},
};
MySolution_Func1(test);
}
public unsafe static void MySolution_Func1(int[][] data) {
var items=new int*[data.Length];
Recurse(0, data, items);
}
public unsafe static void Recurse(int index, int[][] data, int*[] build) {
if(index==data.Length) {
fixed(int** finalp=build) {
Func2(finalp);
}
} else {
fixed(int* nextp=data[index]) {
build[index]=nextp;
Recurse(index+1, data, build);
}
}
}
private unsafe static void Func2(int** data) {
for(var j=0; j<4; ++j) {
for(var i=0; i<j+1; ++i) {
Debug.WriteLine("{0},{1}: {2}", j, i, data[j][i]);
}
}
}
There's no need to copy the whole array. You can create an array of pointers (i.e. IntPtr[]), and then cast that to int**. It's not pretty, and I wouldn't suggest doing it. But it can be done. The code below shows how.
int[][] myArray = new int[10][];
for (int i = 0; i < 10; ++i)
{
int[] x = new int[10];
for (int j = 0; j < 10; ++j)
{
x[j] = 10 * i + j;
}
myArray[i] = x;
}
// Output the array
Console.WriteLine("int[][]");
for (int i = 0; i < 10; ++i)
{
for (int j = 0; j < 10; ++j)
{
Console.Write("{0}, ", myArray[i][j]);
}
Console.WriteLine();
}
// Convert to int*[]
unsafe
{
GCHandle[] handles = new GCHandle[10];
IntPtr[] ArrayOfPointer = new IntPtr[10];
for (int i = 0; i < 10; ++i)
{
handles[i] = GCHandle.Alloc(myArray[i], GCHandleType.Pinned);
ArrayOfPointer[i] = handles[i].AddrOfPinnedObject();
}
// Okay, let's output that
Console.WriteLine("int*[]");
for (int i = 0; i < 10; ++i)
{
int* p = (int*)ArrayOfPointer[i];
for (int j = 0; j < 10; ++j)
{
Console.Write("{0}, ", *p);
++p;
}
Console.WriteLine();
}
// now convert to int**
GCHandle bigHandle = GCHandle.Alloc(ArrayOfPointer, GCHandleType.Pinned);
int** ppInt = (int**)bigHandle.AddrOfPinnedObject();
// and output it
Console.WriteLine("int**");
int** pa = ppInt;
for (int i = 0; i < 10; ++i)
{
int* p = *pa;
for (int j = 0; j < 10; ++j)
{
Console.Write("{0}, ", *p);
++p;
}
Console.WriteLine();
++pa;
}
// Need to free the handles
bigHandle.Free();
for (int i = 0; i < 10; ++i)
{
handles[i].Free();
}
}
public unsafe void ConvertToNative(int[][] jarray, out int** ptr)
{
ptr= (int**)Marshal.AllocHGlobal(jarray.Length*sizeof(int));
for (int i = 0; i < jarray.Length; i++)
{
*(ptr+i) = (int*)Marshal.AllocHGlobal(jarray[i].Length*sizeof(int));
for (int j = 0; j < jarray[i].Length; j++)
{
(*(i + ptr))[j] = jarray[i][j];
}
}
}
This works but uses unmanaged memory, and there is no recursion, is that valid ?
You can do it with O(1) stack space, if you are willing to copy all the data into another buffer:
public unsafe static void AlternateSolution_Func1(int[][] data) {
var buffer=new int[data.Sum(a => a.Length)];
fixed(int* pBuffer=buffer) {
var items=new int*[data.Length];
int count=0;
for(int i=0; i<data.Length; ++i) {
items[i]=pBuffer+count;
var array=data[i];
for(int j=0; j<array.Length; ++j) {
pBuffer[count++]=array[j];
}
}
fixed(int** pItems=items) {
Func2(pItems);
}
}
}

Categories

Resources