Creating array from existing one - c#

This is the code:
class Program
{
void Add2Array(object arr, object item)
{
if (arr.GetType() == typeof(string[]))
{
int iLen = (arr as Array).Length;
var c = Array.CreateInstance(typeof (String), 3);
Array v = Array.CreateInstance((arr as Array).GetValue(0).GetType(), iLen+1); // this works but when if arr is empty it wont work
Array.Copy(ar, v, iLen);
v.SetValue(item, iLen);
}
}
public string[] sarr = new string[1];
static void Main(string[] args)
{
Program p = new Program();
p.sarr[0] = "String Item";
p.Add2Array(p.sarr, "New string item");
}
}
I want to create a method which can take every type of arrays and put new item into them.
Above code is my solution (if you know better please share) and if arr parameter hasn't any item, it won't work properly. Because if I use this Array.CreateInstance(arr.GetType(),3) it will create new array like this v.GetType() => string[2][] because arr is string array and if i create with same type it is returning two dimensonal array.
How can I extend an array(given as a parameter) and put new item into it ?

T[] Add2Array<T>(T[] arr, T item)
{
return arr.Concat(new[]{item}).ToArray();
}

Array cannot be extended. The only thing you could do is to copy data to a new array which is bigger than original one and append data.
BTW, why not to use List<>?
using System;
namespace ConsoleApplication1 {
class Program {
static void Main(string[] args) {
int[] x = new int[]{2,3,5};
int[] y = new ArrayExpander().AddItem(x, 0);
foreach (var i in y)
{
Console.Write(i);
}
}
}
class ArrayExpander
{
public T[] AddItem<T>(T[] source, T item)
{
var destination = new T[source.Length + 1];
Array.Copy(source, destination, source.Length);
destination[source.Length] = item;
return destination;
}
}
}

Related

Generic as parameter, what am I doing wrong?

I am learning basic sort algorithms from some source in github. Now, I am trying to make a method that can be used for all sorter instance but I am facing error CS1503 which says that I can not convert int[] into T[]. The intellisense recommends me to add new method but I don't want to add it. Here is my code:
class Program
{
static void Main(string[] args)
{
test<int>(new BubbleSorter<int>(), new IntComparer());
}
static void test<T>(ISorter<T> sorter, IComparer<T> intComparer)
{
var (correctArray, testArray) = RandomHelper.GetArrays(10); //Generates random arrays
sorter.Sort(testArray, intComparer); //This line error
Array.Sort(correctArray);
Console.WriteLine(string.Join(",", testArray));
Console.WriteLine(string.Join(",", correctArray));
}
}
public interface ISorter<T>
{
void Sort(T[] array, IComparer<T> comparer);
}
class BubbleSorter<T> : ISorter<T>
{
public void Sort(T[] array, IComparer<T> comparer) {//Sort}
}
internal class IntComparer : IComparer<int>
{
public int Compare(int x, int y)
{
return x.CompareTo(y);
}
}
internal static class RandomHelper
{
public static (int[] testArray, int[] correctArray) GetArrays(int n)
{
int[] testArr = new int[n];
int[] correctArr = new int[n];
Random rnd = new Random();
for (int i = 0; i < n; i++)
{
int t = rnd.Next(1, 1000);
testArr[i] = t;
correctArr[i] = t;
}
return (testArr, correctArr);
}
}
What I want to achieve that I want to do this with one test method:
static void Main(string[] args)
{
test<int>(new BubbleSorter<int>(), new IntComparer());
test<int>(new SelectionSorter<int>(), new IntComparer());
test<int>(new MergeSorter<int>(), new IntComparer());
}
test is supposed to be able to work on any T, right? But RandomHelper.GetArrays can only return int[]! To make your test method able to test any T, you need to write a GetArrays method that can generate test cases for any T as well, not just for int.
So now you have two choices:
Make test non-generic because you only need to sort ints here.
Make GetArrays work on any T.
For option 1, you can just remove all the <T> and replace T with int, like this:
class Program
{
static void Main(string[] args)
{
test(new BubbleSorter(), new IntComparer());
}
static void test(ISorter sorter, IComparer<int> intComparer)
{
var (correctArray, testArray) = RandomHelper.GetArrays(10);
sorter.Sort(testArray, intComparer);
// Array.Sort(correctArray); // you should do this in GetArrays instead! You should also pass intComparer to Array.Sort as well!
Console.WriteLine(string.Join(",", testArray));
Console.WriteLine(string.Join(",", correctArray));
}
}
public interface ISorter
{
void Sort(int[] array, IComparer<int> comparer);
}
class BubbleSorter : ISorter
{
public void Sort(int[] array, IComparer<int> comparer) {//Sort}
}
One way to do option 2 is to add a Func<int, T> parameter to GetArrays telling it how to transform an int to a T. You would also need a IComparer<T> parameter to sort the correct array as I mentioned above,
public static (T[] testArray, T[] correctArray) GetArrays<T>(int n, Func<int, T> transform, IComparer<T> comparer)
{
T[] testArr = new T[n];
T[] correctArr = new T[n];
Random rnd = new Random();
for (int i = 0; i < n; i++)
{
int t = rnd.Next(1, 1000);
testArr[i] = transform(t);
correctArr[i] = transform(t);
}
Array.Sort(correctArray, comparer);
return (testArr, correctArr);
}
And you can call GetArrays like this:
static void test<T>(ISorter<T> sorter, IComparer<T> intComparer)
{
var (correctArray, testArray) = RandomHelper.GetArrays(10, x => x, intComparer);
sorter.Sort(testArray, intComparer);
Console.WriteLine(string.Join(",", testArray));
Console.WriteLine(string.Join(",", correctArray));
}

Is is possible to apply a generic method to a list of items?

Lets say I've written my own method to reverse a list in place.
public static void MyReverse<T>(List<T> source)
{
var length = source.Count;
var hLength = length / 2;
for (var i = 0; i < hLength; i++)
{
T temp = source[i];
source[i] = source[length - 1 - i];
source[length - 1 - i] = temp;
}
}
I call it like so, and it works.
var fooList = new List<Foo>();
MyReverse(fooList);
If I want to reverse multiple lists, I call it like so.
var fooList = new List<Foo>();
var barList = new List<Bar>();
var bazList = new List<Baz>();
MyReverse(fooList);
MyReverse(barList);
MyReverse(bazList);
If I want to reverse an arbitrary number of lists, I'd try:
public static void Main(string[] args)
{
var lists = new List<object>
{
new List<Foo>(),
new List<Bar>(),
new List<Bar>()
};
ReverseLists(lists);
}
public static void ReverseLists(List<object> sourceLists)
{
foreach (var sourceList in sourceLists)
{
MyReverse(sourceList); // Error: Type arguments cannot be inferred from usage
}
}
But this throws a compile time error. Is what I'm trying to do possible - could the ReverseLists method be implemented?
Assuming you have a static method like this
public static class ReverseHelper
{
public static void MyReverse<T>(IList<T> source)
{
var length = source.Count;
var hLength = length / 2;
for (var i = 0; i < hLength; i++)
{
T temp = source[i];
source[i] = source[length - 1 - i];
source[length - 1 - i] = temp;
}
}
}
With the help of non generic interface and a generic class you can do it.
public interface IReverser
{
void Reverse();
}
public class ListReverser<T> : IReverser
{
private readonly IList<T> source;
public ListReverser(IList<T> source)
{
this.source = source;
}
public void Reverse()
{
ReverseHelper.MyReverse<T>(source);
}
}
static void Main(string[] args)
{
var lists = new List<IReverser>
{
new ListReverser<Foo>(new List<Foo>()),
new ListReverser<Bar>(new List<Bar>()),
new ListReverser<Bar>(new List<Bar>())
};
foreach (var reverser in lists)
{
reverser.Reverse();
}
}
I've used IList<T> as opposed to List<T> to support broader number of types; If you want List<T> you can put it back.
As per my comment above...
The compiler cannot covert infer the type of T when passed object (which is effectively what's happening)
However there is a much simpler option - which is to just abandon using generics, and change the signature of your MyReverse method to public static void MyReverse(IList source) (and elsewhere replace List<object> with IList)
ie:
public static void Main(string args[])
{
var lists = new List<IList>
{
new List<Foo>(),
new List<Bar>(),
new List<Bar>()
};
ReverseLists(lists);
}
public static void MyReverse(IList source)
{
var length = source.Count;
var hLength = length / 2;
for (var i = 0; i < hLength; i++)
{
var temp = source[i];
source[i] = source[length - 1 - i];
source[length - 1 - i] = temp;
}
}
public static void ReverseLists(List<IList> sourceLists)
{
foreach (var sourceList in sourceLists)
{
MyReverse(sourceList); // Error: Type arguments cannot be inferred from usage
}
}
public class Foo
{
}
public class Bar
{
}
To compliment the answer from Sriram Sakthivel - the key to your problem is that the Type cannot be inferred from what you are passing in. It's worth noting that List<T> implements IList so your issue above can be reframed using a parameter array of List like:
void Main()
{
var fooList = new List<string>();
var barList = new List<string>();
var bazList = new List<string>();
ReverseLists(fooList, barList, bazList);
}
public static void ReverseLists(params IList [] sourceLists)
{
foreach (var sourceList in sourceLists)
{
MyReverse(sourceList);
}
}
public static void MyReverse(IList source)
{
var length = source.Count;
var hLength = length / 2;
for (var i = 0; i < hLength; i++)
{
var temp = source[i];
source[i] = source[length - 1 - i];
source[length - 1 - i] = temp;
}
}
If you change your ReverseLists method signature to
public static void ReverseLists<T>(IEnumerable<object> sourceLists)
{
foreach (var sourceList in sourceLists.OfType<List<T>>())
{
MyReverse(sourceList);
}
}
Then you can call this for each list type:
ReverseLists<Foo>(lists);
ReverseLists<Bar>(lists);
Maybe not ideal having to call it once per list type, but a comparatively small change to your existing code.
change this line in the original post:
MyReverse(sourceList); // Error: Type arguments cannot be inferred from usage
to this:
MyReverse(((System.Collections.IList)sourceList).Cast<object>().ToList());

Reassign an array of classes indexes (reference type)

Consider the following code:
internal class A
{
public int X;
}
private void test()
{
A[] Collection = new A[2];
Collection[0].X = 1;
Collection[1] = Collection[0]
Collection[0] = new A();
Collection[0].X = 2;
//The code above produces: Collection[1] displays 2, and Collection[0] displays 2.
//Wanted behaviour: Collection[1] should display 1, and Collection[0] display 2.
}
Since the array of classes, Collection, is a reference type. Collection[0] points to same memory region that Collection[1] does.
My question is, how can i "copy" Collection[0] values to Collection[1] so i get the following output:
Collection[1].X returns 1, and Collection[0].X returns 2.
here is a example
internal class A
{
public int X;
}
private void test()
{
A[] Collection = new A[2];
Collection[0].X = 1;
CopyPropertyValues(Collection[0],Collection[1]);
Collection[0] = new A();
Collection[0].X = 2;
}
public static void CopyPropertyValues(object source, object destination)
{
var destProperties = destination.GetType().GetProperties();
foreach (var sourceProperty in source.GetType().GetProperties())
{
foreach (var destProperty in destProperties)
{
if (destProperty.Name == sourceProperty.Name &&
destProperty.PropertyType.IsAssignableFrom(sourceProperty.PropertyType))
{
destProperty.SetValue(destination, sourceProperty.GetValue(
source, new object[] { }), new object[] { });
break;
}
}
}
}
You should have class 'A' implement a 'Clone' method and then instead of:
Collection[1] = Collection[0];
use:
Collection[1] = Collection[0].Clone();
Alternatively, you could change class 'A' to a struct, but that would have other unintended consequences.

C# - Nestable, bounded arrays

I'm porting a game written in Pascal (compiled in 16 bit) to C# (so it will run on machines newer than XP). From what I've gathered, in Pascal, it's possible to type define in the type section of a unit/program through syntax like this:
type
BaseArrayPtr = ^BaseArray;
BaseArray = array [1 .. 5, 1 .. 5] of Integer;
SubArray = array [0 .. 3] of BaseArray;
I also gathered that, unfortunately, it is impossible to type define in C#. However, I'm trying for a workaround. So far, this is what I have:
BoundedArray.cs:
using System;
using System.Collections;
namespace test
{
abstract class BoundedArray<T>
{
public BoundedArray()
{
m_data = null;
}
public T this[params int[] index]
{
get
{
if (index.Length != m_data.Rank)
throw new IndexOutOfRangeException();
return (T) m_data.GetValue(index);
}
set
{
if (index.Length != m_data.Rank)
throw new IndexOutOfRangeException();
m_data.SetValue(value, index);
}
}
protected void SetAttributes(int[] lowerBounds, int[] lengths)
{
if (lengths.Length != lowerBounds.Length)
throw new ArgumentException();
m_lowerBounds = lowerBounds;
m_lengths = lengths;
m_data = Array.CreateInstance(typeof(T), m_lengths, m_lowerBounds);
m_data.Initialize(); // Should (but doesn't) initialize every element in m_data
}
Array m_data;
int[] m_lengths;
int[] m_lowerBounds;
}
}
test.cs:
using System;
namespace test
{
class Program
{
public static int[] ints(params int[] values)
{
return values;
}
class BaseArray : BoundedArray<int>
{
public BaseArray()
{
SetAttributes(ints(2, 2), ints(1, 2));
}
}
class SubArray : BoundedArray<BaseArray>
{
public SubArray()
{
SetAttributes(ints(4), ints(2));
}
}
static void Main(string[] args)
{
SubArray subArray = new SubArray();
Console.Read();
}
}
}
I've checked baseArray, and the default values of m_data are zeroes, since they are ints. However, in subArray, the default values of m_data are null - the BaseArray instances inside the array in subArray haven't been initialized for some reason. How do I get the default constructor to run?
EDIT: The real question at the moment is why doesn't m_data.Initialize(); in the SetAttributes method initialize all elements in m_data? The documentation on MSDN seems to indicate that it should...
EDIT:
So I believe that problem is that System.Array.Initialize only works on value-types. Since classes are references types in C#, System.Array.Initialize doesn't do anything. So I have to find a way to initialize a reference-type array of variable dimensions, lengths, and lower bounds.
Well I have done some changes that when you want to create an instance of a SubArray you should pass BaseArray as source of data to be initialize.
As i understood you want to set the values from BaseArray to SubArray.
Here is my work:
BoundedArray.cs
abstract class BoundedArray<T>
{
public BoundedArray()
{
m_data = null;
}
public int[] Lengths;
public int[] LowerBounds;
public void CreateInstance()
{
if (Lengths.Length != LowerBounds.Length)
throw new Exception("Incorrect number of lengths or lower bounds.");
m_data = Array.CreateInstance(typeof(T), Lengths, LowerBounds);
}
public void CreateInstance(Array source)
{
if (Lengths.Length != LowerBounds.Length)
throw new Exception("Incorrect number of lengths or lower bounds.");
m_data = Array.CreateInstance(typeof(T), Lengths, LowerBounds);
/************************************************************************/
/* Now you should find the value of BaseArray and set it to m_data */
/************************************************************************/
}
public T this[params int[] index]
{
get
{
if (index.Length != m_data.Rank)
throw new IndexOutOfRangeException();
return (T)m_data.GetValue(index);
}
set
{
if (index.Length != m_data.Rank)
throw new IndexOutOfRangeException();
m_data.SetValue(value, index);
}
}
public Array GetData()
{
return m_data;
}
Array m_data;
}
Test.cs
class Program
{
public static int[] ints(params int[] values)
{
return values;
}
class BaseArray : BoundedArray<int>
{
public BaseArray()
{
Lengths = ints(1, 2);
LowerBounds = ints(2, 2);
CreateInstance();
}
}
class SubArray : BoundedArray<BaseArray>
{
public SubArray(BaseArray arr)
{
Lengths = ints(2);
LowerBounds = ints(4);
CreateInstance(arr.GetData());
}
}
static void Main(string[] args)
{
BaseArray baseArray = new BaseArray();
SubArray subArray = new SubArray(baseArray);
Console.Read();
}
}
You have a singe-dimensional array SubArray which holds BaseArray objects which are two-dimensional arrays of intergers. In place of Pascal type, you can define a custom C# class which would override the indexer operator to give you exactly the same behavior.
EDITED
So, in Pascal you have this:
type
BaseArrayPtr = ^BaseArray;
BaseArray = array [1 .. 5, 1 .. 5] of Integer;
SubArray = array [0 .. 3] of BaseArray;
Maybe I misunderstood the question, but is the below not exactly the same, in C#?
public class BaseArray
{
int[,] m_array = new int[5, 5];
static void CheckBounds(int x, int y)
{
if (x < 1 || x > 5 || y < 1 || y > 5)
throw new IndexOutOfRangeException();
}
public int this[int x, int y]
{
get
{
CheckBounds(x, y);
return m_array[x-1, y-1];
}
set
{
CheckBounds(x, y);
m_array[x-1, y-1] = value;
}
}
}
public class SubArray
{
BaseArray[] m_array = new BaseArray[4];
public BaseArray this[int x]
{
get { return m_array[x]; }
set { m_array[x] = value; }
}
}
I've already answered my own question once, but I came up with a much better implementation of my answer.
Here's what this solution consists of:
SetAttributes must be run once, in the default constructor of a class based off of BoundedArray
During SetAttributes, I gather a jagged, two-dimensional array of all of the indices in the current BoundedArray subclass
I create instances of the template type by calling Activator.CreateInstance and assigning one per index
Other things to note:
Set attributes now takes a variable length array of int[]s instead of two int[]s. Previously, it was taking the lowerbounds and the lengths, but I realized it makes more sense to just take int[]s which are lower and upper bounds, and then use a LINQ query to check that there aren't any which aren't pairs
I created a static class called IntArray, which is used extensively by SetAttributes and in test.cs
I tried to throw as many useful errors as possible, since I'll probably end up using this code a lot
I have a feeling that Combinations(int[][] list1, int[] list2) is probably where the most improvement on my solution could be found. I'm open to suggestions on how to improve all of my code
So, without further ado, my complete solution:
BoundedArray.cs
using System;
using System.Linq;
using System.Collections.Generic;
namespace test
{
static class IntArray
{
public static int[] FromValues(params int[] values)
{
return values;
}
public static int[] Sequence(int from, int length)
{
if (from < 0 || length < 1)
throw new ArgumentException();
return Enumerable.Range(from, length).ToArray();
}
public static int[][] Combinations(int[] list1, int[] list2)
{
return Combinations(list1.Select(i => new int[] { i }).ToArray(), list2);
}
public static int[][] Combinations(int[][] list1, int[] list2)
{
List<List<int>> result = new List<List<int>>();
for (int i = 0; i < list1.Length; i++)
{
for (int j = 0; j < list2.Length; j++)
result.Add(((int[]) list1.GetValue(i)).Concat(new int[] { list2[j] }).ToList());
}
return result.Select(i => i.ToArray()).ToArray();
}
}
abstract class BoundedArray<T>
{
public BoundedArray()
{
m_data = null;
}
public Array Value
{
get { return m_data; }
}
public T this[params int[] index]
{
get
{
if (index.Length != m_data.Rank)
throw new IndexOutOfRangeException();
return (T) m_data.GetValue(index);
}
set
{
if (index.Length != m_data.Rank)
throw new IndexOutOfRangeException();
m_data.SetValue(value, index);
}
}
protected void SetAttributes(params int[][] values)
{
// Make sure all of the values are pairs
if (values.Where(i => i.Length != 2).ToArray().Length > 0)
throw new ArgumentException("Input arrays must be of length 2.");
int[] lowerBounds = values.Select(i => i[0]).ToArray();
int[] lengths = values.Select(i => i[1] - i[0] + 1).ToArray();
m_data = Array.CreateInstance(typeof(T), lengths, lowerBounds);
int[][] indices = (lowerBounds.Length != 1) ?
IntArray.Combinations(IntArray.Sequence(lowerBounds[0], lengths[0]), IntArray.Sequence(lowerBounds[1], lengths[1]))
: IntArray.Sequence(lowerBounds[0], lengths[0]).Select(i => new int[] { i }).ToArray();
for (int i = 2; i < lowerBounds.Length; i++)
indices = IntArray.Combinations(indices, IntArray.Sequence(lowerBounds[i], lengths[i]));
for (int i = 0; i < indices.Length; i++)
m_data.SetValue(Activator.CreateInstance(typeof(T)), indices[i]);
}
Array m_data;
}
}
test.cs
using System;
namespace test
{
class Program
{
// *** Examples of what you can do with BoundedArray ***
// Multi-dimensional, bounded base array
class BaseArray : BoundedArray<int>
{
public BaseArray()
{
SetAttributes(IntArray.FromValues(2, 3), IntArray.FromValues(2, 4));
}
}
// One-dimensional, bounded subclass array
class SubArray : BoundedArray<BaseArray>
{
public SubArray()
{
SetAttributes(IntArray.FromValues(4, 6));
}
}
static void Main(string[] args)
{
// Initializations used for testing purposes
BaseArray baseArray = new BaseArray();
SubArray subArray = new SubArray();
// Example of assignment
baseArray[3, 4] = 3;
subArray[4][2, 3] = 4;
subArray[4][2] = 3; // Weakness: compiles, but causes IndexOutOfRangeException
Console.Read();
}
}
}
Thougts?

Retrieve values from next and previous elements in Sorted List C#

I have a sorted list that will pass in two elements and compare the two. Is there a function in the SortedList class in C# that will do a next and previous? I got some help with a .Skip, but since the keys would be variable, how would that work? All I need to do is take in the first element and second element, then skip to the third and fourth, fifth and sixth, etc. I wish it were as simple as LinkedList's ".next.next."
double velocity = positionList.Values.Skip(1);
Edit: The positionList is type
<double, HandCoordinate>
HandCoordinate = {double, double, double}
Does that help?
Thanks!
The class SortedList inherites IEnumerator, so you can use it:
SortedList list = ...
var listEnumerator = ((IEnumerable)list).GetEnumerator();
Pair<MyType> pair = null
do
{
pair = Pair.Next<MyType>(listEnumerator);
...
}
while(pair != null)
...
class Pair<T>
{
public T First {get; set;}
public T Second {get; set;}
public static Pair<T> Next<T>(IEnumerator enumerator)
{
var first = enumerator.Current;
if(enumerator.MoveNext())
{
return new Pair<T>
{
First = (T)first,
Second = (T)enumerator.Current,
}
}
return null;
}
}
List<int> ints = new List<int>();
ints.Add(1);
ints.Add(2);
ints.Add(3);
ints.Add(4);
for (int i = 0; i < ints.Count; i += 2)
{
var pair = ints.Skip(i).Take(2);
var first = pair.First();
var last = pair.Last();
}
Note: This should work, irrelevant of the type in theory. Unless the type is a drastically different format.
Without Skip().
var pair = new { First = ints[i], Second = ints[i += 1] };
The question is somewhat unclear. I'm assuming you need to get pairs of things from a list?
It's fairly easy to write an extension method that will present a sequence of pairs of items from an IEnumerable:
using System;
using System.Collections.Generic;
namespace Demo
{
internal static class Program
{
public static void Main()
{
double[] test = new double[] {1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
foreach (var pair in test.AsPairs()) // This is how you use it.
{
Console.WriteLine("({0}, {1})", pair.Item1, pair.Item2);
// Or simply: Console.WriteLine(pair);
}
}
}
public static class EnumerableExt
{
public static IEnumerable<Tuple<T, T>> AsPairs<T>(this IEnumerable<T> sequence)
{
bool isFirst = true;
T first = default(T);
foreach (var item in sequence)
{
if (isFirst)
{
first = item;
isFirst = false;
}
else
{
isFirst = true;
yield return new Tuple<T, T>(first, item);
}
}
}
}
}

Categories