I am pretty new to lambda expressions and am trying to write a simple program here to understand the use of Func<> and can't understand why I cannot loop through an input array using indexing?
class Program
{
static void Main(string[] args)
{
int[] array = new int[4];
array[0] = -1; array[1] = 2; array[2] = 3; array[3] = 8;
Func<Array, int> DoSomething = inputarray =>
{
for (int i = 0; i < inputarray.Length; i++)
{
if (inputarray[i] > inputarray[i + 1])
{
//;
}
}
return 1;
};
}
}
This gives an error saying
cannot apply indexing with [] to an expression of type Array
How do I resolve this? Basically, how would I loop through my input array?
A System.Array is the base class of all arrays like an int[]. It implements also IList which allows to access items by index, but the Item property is implemented as an explicit interface member implementation. It can be used only when the Array instance is cast to an IList interface:
var list = (System.Collections.IList)inputarray;
Now you can use the indexer but it will return objects not ints, so you can't use following without casting because objects can't be compared with >:
if (list[i] > list[i + 1])
{
//;
}
I guess you want to use an int[]:
Func<int[], int> DoSomething = inputarray =>
// ...
You need to provide a type for the Array in the example you show.
try:
Func<int[], int> DoSomething
instead.
Related
I am trying to make my own multithreaded mergesort algorithm by using an ArrayList. I am familiar with this method in Java but trying to bring it over to c# is not working as planned. I get the following error when trying to compare two ArrayList items Error 1 Operator '<' cannot be applied to operands of type 'object' and 'object'. I know you cannot directly compare two objects like that, in Java you can use compareTo or something like that, is there any equivalent for c#?
Here is the code causing the error in case you need it, bear in mind that I copied this from one of my Java programs that worked with integer arrays.
int size = (last - first) + 1;
ArrayList temp = new ArrayList();
int mid = (first + last) / 2;
int i1 = 0;
int i2 = first;
int i3 = mid + 1;
while(i2 <= mid && i3 <= last)
{
if(list[i2] < list[i3])
temp[i1++] = list[i2++];
else temp[i1++] = list[i3++];
}
while(i2 <= mid)
temp[i1++] = list[i2++];
while(i3 <= last)
temp[i1++] = list[i3++];
i3 = first;
for(i1 = 0; i1 < temp.Count; i1++, i3++)
list[i3] = temp[i1];
I think just use a SortedList of ints.
var sl = new SortedList();
sl.Add(15, 15);
sl.Add(443, 443);
sl.Add(2, 2);
sl.Add(934, 934);
sl.Add(55, 55);
foreach (var item in sl.Values)
{
Console.WriteLine(item); // Outputs 2, 15, 55, 443, 934
}
Or else a generic List and call Sort (better perf I think).
var list = new List<int>();
list.Add(5);
list.Add(1);
list.Add(59);
list.Add(4);
list.Sort();
foreach (var element in list)
{
Console.WriteLine(element); // Outputs 1, 4, 5, 59
}
I would suggest looking into the IComparer<T> interface. You can make a version of your MergeSort algorithm that takes an IComparer<T> which can be used to compare the objects for sorting. It would probably give you similar functionality to what you are used to.
You could do this in addition to defining a version of MergeSort that restricts the type to IComparable<T>. This way, between both versions of the function, you can handle objects that implement the interface already and also allow your users to provide a comparison for objects that don't implement it.
You could put the MergeSort in as an Extension Method on the IList<T> interface as such.
public static class MergeSortExtension
{
public static IList<T> MergeSort<T>(this IList<T> list) where T : IComparable<T>
{
return list.MergeSort(Comparer<T>.Default);
}
public static IList<T> MergeSort<T>(this IList<T> list, IComparer<T> comparer)
{
// Sort code.
}
}
You could cast each item to IComparable or do an as IComparable and check for null (casting will throw an exception if the object instance doesn't implement the interface). But what #DavidG L suggested probably the way to go. But make a constraint on T that it must implement IComparable.
Taking all of your suggestions into account I have come up with the following solution:
public static void merge(List<T> list , int first, int last) {
int size = (last - first) + 1;
List<T> temp = new List<T>();
IEnumerable<IComparable> sorter = (IEnumerable<IComparable>)list;
int mid = (first + last) / 2;
int i1 = 0;
int i2 = first;
int i3 = mid + 1;
while(i2 <= mid && i3 <= last)
{
if (sorter.ElementAt(i2).CompareTo(sorter.ElementAt(i3)) < 0)
temp[i1++] = list[i2++];
else temp[i1++] = list[i3++];
}
while(i2 <= mid)
temp[i1++] = list[i2++];
while(i3 <= last)
temp[i1++] = list[i3++];
i3 = first;
for(i1 = 0; i1 < temp.Count; i1++, i3++)
list[i3] = temp[i1];
}
Thank you for all the help, I do not get any errors anymore.
The problem is that ArrayList is not a generic collection, so it allows to call only object's methods on any item. You can use LINQ to cast to generic IEnumerable<int>, then you will be able to call methods on int, including comparing and ordering:
ArrayList al = new ArrayList();
al.Add(1);
al.Add(2);
IEnumerable<int> coll = al.Cast<int>();
if (coll.ElementAt(0) < coll.ElementAt(1))
// ...
or:
var ordered = coll.OrderBy(n => n).ToList();
If your ArrayList contains objects of different types, you should use OfType<int> to filetr out ints, but the proper way would be to use a typed collection like List<int> instead of ArrayList.
I have a method that generates an array. I want to return this array so I can use it another method. Here is my code so far:
public static Array[] generateFirstArray(int seedValue)
{
int[] firstArray = new int[20];
Random randomNumber = new Random(seedValue);
for (int i = 0; i < firstArray.Length; i++)
{
firstArray[i] = randomNumber.Next(0, 4);
}
return firstArray;
}
But when I run it, I get the following error:
Error 1 Cannot implicitly convert type 'int[]' to 'System.Array[]'
I tried to add [] after firstArray but still not working.
Your return type is currently an array of Array objects. Change your return type to an array of ints (int[]):
public static int[] generateFirstArray(int seedValue)
The signature of your methods says you're trying to return an Array of Array (Array[]).
You want to return an int[] instead so just change your signature to
public static int[] generateFirstArray(int seedValue)
the return type of your method must be int[] and not Array[]
Here is one more way of implementing it
int Min = 0;
int Max = 4;
Random randNum = new Random(seedValue);
int[] firstArray = Enumerable
.Repeat(0, 20)
.Select(i => randNum.Next(Min, Max))
.ToArray();
return firstArray;
How would I use the following LINQ query correctly? I want to create a one-dimensional array that contains only values that are greater than 5. I can't understand why it can't iterate over this multidimensional array, but if I use foreach, it actually iterates.
// Create an multidimensional array, then just put numbers into it and print the array.
int[,] myArr = new int[5,6];
int rows = myArr.GetLength(0);
int cols = myArr.GetLength(1);
for (int i = 0; i < rows; i++)
{
for (int k = 0; k < cols; k++)
{
myArr[i,k] = i + k;
Console.Write(myArr[i,k]);
}
Console.WriteLine("");
}
var highList = from val in myArr where (val > 5) select val;
The error is:
Could not find an implementation of the query pattern for source type 'int[*,*]'. 'Where' not found. Are you missing a reference or a using directive for 'System.Linq'?
I thought this might fix the problem:
public static IEnumerator<int> GetEnumerator(int[,] arr)
{
foreach(int i in arr)
{
yield return i;
}
}
But it doesn't implement the iterator.
The problem is that multi-dimensional (rectangular) arrays implement IEnumerable, but not IEnumerable<T>. Fortunately, you can use Cast to fix that - and Cast gets called automatically if you explicitly specify the type of the range variable:
var highList = from int val in myArr where (val > 5) select val;
Or without the unnecessary brackets:
var highList = from int val in myArr where val > 5 select val;
Or using method calls directly, given that it's a pretty trivial query expression:
var highList = myArr.Cast<int>().Where(val => val > 5);
I think this will box each element, however. You could add your own Cast extension method to avoid that:
public static class RectangularArrayExtensions
{
public static IEnumerable<T> Cast<T>(this T[,] source)
{
foreach (T item in source)
{
yield return item;
}
}
}
I have moved from C to C#.
I have a function which accepts an array. I want to pass one dimension of a Two Dimensional array to this function.
C Code would be:-
void array_processing(int * param);
void main()
{
int Client_ID[3][50];
/* Some
Processing
which fills
this array */
array_processing(&Client_ID[1]);
}
Now, When I want to do same in C#, How can I pass this array?
Function defination will look like:-
private void array_processing(ref int[] param);
and Array would be declared as :-
int[,] Client_ID = new int[3,50];
Now How can I pass Client_ID[1] to the function array_processing()??
By doing array_processing ( ref Client_ID[1]) shouts as "Wrong Number of Indices"!
You can't really do that. C# is less outgoing about its arrays, and prevents you from doing C-like manipulations. This is a good thing.
You have various options:
Create a 1D array and copy your 2D row to it.
Use a jagged array - an array of arrays, which is more like what C lets you do.
Have an array_processing overload that takes a 2D array and a row number.
If you really want to access a 2D row as a 1D array, you should create a 'RowProxy' class that will implement the IList interface and let you access just one row:
class RowProxy<T>: IList<T>
{
public RowProxy(T[,] source, int row)
{
_source = source;
_row = row;
}
public T this[int col]
{
get { return _source[_row, col]; }
set { _source[_row, col] = value; }
}
private T[,] _source;
private int _row;
// Implement the rest of the IList interface
}
Use a lambda expression that will lose the array semantics, but is rather cool:
var ClientId = ...;
var row_5_accessor = (c=>ClientId[5, c]);
You can use row_5_accessor as a function, row_5_accessor(3) will give you ClientId[5, 3]
You can use a jagged array
// Initialize jagged array
int[][] clientID = new int[3][];
for (int i=0; i<clientId.Length; i++)
{
clientId[i] = new int[50];
}
array_processing(ref clientId[1]);
And your method:
private void array_processing(ref int[] subArray);
Just declare method
private void ParseArray(int[,] ar)
{
// Some work...
}
UDP: Code format
A primitive way would be:
var dimNumber = 1;
int[] oneDimension = new int[50];
for(var i=0; i<50; i++)
{
oneDimension[i] = Client_ID[dimNumber][i];
}
array_processing ( ref oneDimension);
I would suggest using Lambda expressions like in the way 5 of zmbq's answer.
You could declare you array as
int[][] Client_ID = new[] { new int[50], new int[50], new int[50] };
and then you can pass it to your array_processing function
array_processing(ref Clinet_ID[1]);
Sorry for miss of my pen.
Late to the conversation, but here is a jagged array example to do this:
string[][] rows = GetStringArray(values);
string[] row = rows[0];
You would set up your jagged array something like:
// rowCount from runtime data
stringArray = new string[rowCount][];
for (int index = 0; index < rowCount; index++)
{
// columnCount from runtime data
stringArray[index] = new string[columnCount];
for (int index2 = 0; index2 < columnCount; index2++)
{
// value from runtime data
stringArray[index][index2] = value;
}
}
I'm trying to use CodeDom to generate C# (.Net 2.0) code that would do the following:
int[][] myArray = new int[someSize][];
In CodeDom, initializing an array requires a CodeArrayCreateExpression. The MSDN says:
If a language allows arrays of arrays, it is possible to create them by nesting a CodeArrayCreateExpression within a CodeArrayCreateExpression.
The way I understand it, the only possibility is to write something like this:
// Declaration and initialization of myArray
CodeVariableDeclarationStatement variable =
new CodeVariableDeclarationStatement("System.Int32[][]", "myArray",
new CodeArrayCreateExpression("System.Int32[][]",
new CodeExpression[] { new CodeArrayCreateExpression("System.Int32[]", 0) }));
But this generates this:
int[][] myArray = new int[][] { new int[0] };
That's not perfect but I could do with it if I knew the size of myArray at generation time, which I don't.
I could write a function that does the initialization and call it in CodeDom but it would be nicer if I could do it in pure CodeDom. Did I miss something ?
[EDIT] Background information
The idea is to automatically generate an adapter between two object representations. I have a meta-description (some kind of IDL) saying: "I have a container object which has a field of type int[][]" and two representations of this container:
// Internal representation
public class InternalContainer {
int[][] myArray;
}
// Network representation
public class NetworkContainer {
int[][] myArray;
}
Thus the question of generating code that can adapt to any size of array.
You have the following workaround to create a jagged array with a dynamic length:
Create the dom equivalent of
ELEMENTTYPE[] array = (ELEMENTTYPE[])Array.CreateInstance(typeof(ELEMENTTYPE), length);
ELEMENTTYPE can be any type, be it an array or not.
Here's my solution, using a CodeSnippetExpression
public static DOM.CodeExpression NewArray (this Type type, int dim, int size) {
string dims = String.Concat(Enumerable.Repeat("[]", dim - 1).ToArray());
return new DOM.CodeSnippetExpression(string.Format("new {0}[{1}]{2}", type.FullName, size, dims));
}
CodeArrayCreateExpression CodeArrayCreateExpression(Array array)
{
CodeArrayCreateExpression arrayCreateExpression = new CodeArrayCreateExpression(array.GetType(), array.GetLength(0));
if (array.GetType().GetElementType().IsArray)
{
CodeArrayCreateExpression[] values = new CodeArrayCreateExpression[array.GetLength(0)];
for (int j = 0; j < array.GetLength(0); j++)
{
values[j] = this.CodeArrayCreateExpression((Array)array.GetValue(j));
}
arrayCreateExpression.Initializers.AddRange(values);
}
else if(array.GetType().GetElementType().IsPrimitive)
{
CodeCastExpression[] values = new CodeCastExpression[array.GetLength(0)];
for (int j = 0; j < values.Length; j++)
{
values[j] = new CodeCastExpression();
values[j].Expression = new CodePrimitiveExpression(array.GetValue(j));
values[j].TargetType = new CodeTypeReference(array.GetType().GetElementType());
}
arrayCreateExpression.Initializers.AddRange(values);
}
return arrayCreateExpression;
}