For a school project, I need to return the number of elements in a generic array (a T[] array).
In the constructor I set the array like this:
T[] arr = new T[100];
arr.add(3);
arr.add(2);
arr.add(1);
To find the size of the array I tried array.length, however this return the capacity which would be 100 but it should be 3.
How could I find the correct answer 3?
EDIT:
The add function is a simple function that checks if the size is smaller than default_capacity add data to array. Size variable is crucial and the function expects the total number of elements in the array.
public void Add(T x)
{
if(size < DEFAULT_CAPACITY)
{
array[size] = x;
}
}
Here the array has not a capacity of 100: it has 100 items.
An array has no capacity, it has Length items...
For example, an array of 100 integers has 100 boxes initialized to 0.
And an array has no add method...
You may use a List<T> instead and you'll have Count property and Add method.
List<> is more smooth and usefull than arrays, but a little less optimized.
If the work is to use a such initialized array, you may use #itsme86 advice in question comment.
But here what is add method in your code?
You can use your intended array like that:
public class GenericArray<T>
{
public readonly T[] arr = new T[100];
}
var myArray = new GenericArray<int>();
myArray.arr[0] = 3;
myArray.arr[1] = 2;
myArray.arr[10] = 1;
And you still have 100 items: myArray.arr.Length is 100.
You can use a generic list like that:
public class GenericList<T>
{
public readonly List<T> list = new List<T>(100);
}
var myList = new GenericList<int>();
myList.list.Add(3);
myList.list.Add(2);
myList.list.Add(1);
And here you have 3 items: myList.list.Count is 3.
The list has here a capacity of 100: it means you can add items without resizing the internal array.
Related
Why does assigning values to a List have to be done with Add but to an array it can be done with the [] operator?
For example:
string[] y = new string[10];
y[0] = "asdf"; //fine
List<string> x = new List<string>(10);
x[0] = "asdf"; //ArgumentOutOfRangeException
Shouldn't both have the same behavior?
Taking a look at the source code for List(of T), your see that the indexed property getter/setters look like this:
// Sets or Gets the element at the given index.
//
public T this[int index] {
get {
// Fllowing trick can reduce the range check by one
if ((uint) index >= (uint)_size) {
ThrowHelper.ThrowArgumentOutOfRangeException();
}
return _items[index];
}
set {
if ((uint) index >= (uint)_size) {
ThrowHelper.ThrowArgumentOutOfRangeException();
}
_items[index] = value;
_version++;
}
}
Notice that, before setting the corresponding item in the List's internal array, it first checks the private _size variable to make sure it is in range. _size is not set to the size of the array, however. Size is incremented/decremented in the List's various Add/Remove methods, so even if you instantiate a list with an initial capacity of 10, that is the internal capacity of the List's array. Here is the constructor:
// Constructs a List with a given initial capacity. The list is
// initially empty, but will have room for the given number of elements
// before any reallocations are required.
//
public List(int capacity) {
if (capacity < 0) ThrowHelper.ThrowArgumentOutOfRangeException(ExceptionArgument.capacity, ExceptionResource.ArgumentOutOfRange_SmallCapacity);
_items = new T[capacity];
}
The _size is not set (and therefore remains as its initialized value of 0) unless you either use Add/Remove/AddRange/etc. or use the constructor that accepts an IEnumerable (in which case the size because the number of items in the IEnumerable).
It makes sense if you think about it. The idea of a list is so that you DON'T have to worry about the complexity (and ugliness) of numeric indexes and resizing/copying arrays when the capacity needs to change. The size of the internal array, after the List is instantiated, should be of no concern to the developer. If you want to micromanage how the internal array is utilized, then you should either create your own implementation, or just use an array.
The way you implemented your array is right.
The size of an array needs to be declared when it is created. There is no way around that.
However, Lists' sizes are more flexible. You can add as many elements as you want without having to declare an initial size. After you've added elements however, you can access or edit them through their index number. Here's an example.
You are getting that exception because technically the list doesn't fill an index until you actually add a value to it. Let me know if that clears it up.
//You can add your elements when you instantiate it
List<string> names = new List<string>{"Alex", "Tommy", "Bob"};
//Or you can add them later
List<string> cities = new List<string>();
cities.Add("Denver");
cities.Add("New York");
//Now that they are created you can access or edit any of the elements within them.
names[2] = "Gerard";
cities[1] = "San Francisco";
The internal structure of a list is different of an array. While in a array you have a size of items defined on its definition, the amout of memory necessary to have these objects is realocate in memory by the CLR.
In a list<T> you can define the maximum of items in a list. That is (part of) the reason you have to call the Add method to add objects in a list<T>. You can define a initial Capacity for a list as you did on the constructor. If you need to add more than the capacity, the list will rearrange it for you. The framework manages for you how much items you have on the list.
Another important thing is that in both cases, you can access by index. For sample:
var obj = list[1];
var obj2 = array[1];
In a case that you do not have the 1 index on the list<T>/array, in an array, you get the default(T) (considering T as your type) and in a list you will get an Exception.
This constructor does not create any elements in list. It just reserves memory for items that could be added to this list.
You still have to insert items to the list manually before you can use then this way.
Upd:
This overload could help you when you dealing with large collections and you almost sure that you'll put about N items into your list. Thus you can reserve memory on creation and avoid memory allocation while you add items into this list (which could be slow sometimes).
I have the following:
public static class LocalFileModelList
{
public static List<LocalFileModel> ModelList = new List<LocalFileModel>();
}
public class LocalFileModel
{
public string Name { get; set; }
public string Extension { get; set; }
}
Then a method to read all files from a directory.
public static List<LocalFileModel> GetAllFiles(string path)
{
var files = Directory.GetFiles(path, "*.*");
foreach(var file in files)
{
var Extension = Path.GetExtension(file);
var Filename = Path.GetFileNameWithoutExtension(file);
var model = new LocalFileModel
{
Name = Filename,
Extension = Extension,
};
LocalFileModelList.ModelList.Add(model);
}
return LocalFileModelList.ModelList;
}
I noticed that, as I step through my code, when I create a new instance of LocalFileModel, populate it with data then add it to the list. Automatically the list created three additional instances of type null. Once those three were populated with their respective objects, it would again create thre more null instances...
I just realized this now, this is normal?
List<T> has an internal array, with a certain capacity which is always equal to or greater than the number of items on the list.
list.Capacity >= list.Count
You can actually tell the list what capacity its internal array should be created with.
new List<int>(capacity: 5);
When an item is inserted, and the array is at its capacity, the list creates a new array with double the previous size to accommodate the new element. So, in your case, if you were to insert a 5th item, the list would allocate a new internal array with 8 slots (5 of which would be filled).
For more details, check the implementation here.
Yes. .NET and most other libraries allocate a list or a vector with extra space (capacity) so it doesn't constantly have to resize and copy the data. The Size determines what is accessible.
The default capacity is defined in here to 4 (but the docs doesn't have to be):
http://referencesource.microsoft.com/#mscorlib/system/collections/generic/list.cs,aa9d469618cd43b0,references
The initial capacity of the internal array held by List<T> is 4 (currently, that is an implementation detail and may change), granted you added an initial value. Once you start filling the list, it will resize itself by a multiple of 2 each time. That is why when you know ahead of time the number of minimum items, you can use the overload taking int capacity (or use an array if it's really a fixed size).
List<T> is backed by an array. The default/Initial capaicity of List<T> is defined as 4 as in reference source, but it doesn't take affect until an item is added to a list.
public class List<T> : IList<T>, System.Collections.IList, IReadOnlyList<T>
{
private const int _defaultCapacity = 4;
So when you added the first item in your List, the size is set to 4 using the following check in EnsureCapacity method:
int newCapacity = _items.Length == 0? _defaultCapacity : _items.Length * 2;
Later on, with each new item being added to the list, the capacity increases to Number of Elements * 2
That is why, when you add the first item, you can see three null spaces, three additional spaces reserved in your list.
I am new to c# and am trying to build an array of arrays of items. I have looked at 2d arrays and jagged arrays and simply can't work out what i'm supposed to be using and can not get it to work. It's not so much building the array it's then looping through it to interrogate the array elements. I'm working within an existing library which is where all the variables come from, most of the other supporting code I've left out as it's not relevant. Once a instance is found i'm then trying to update a field from 0 to 1. Many thanks for any help in advance.
//Declare array
private double[,] myOpenTrades;
private void mymethod (double score, double RSIComboScore, int type, int line)
{
myOpenTrades[line,0] = type;
myOpenTrades[line,1] = CurrentBar;
myOpenTrades[line,2] = Close[0];
myOpenTrades[line,3] = rewardClose;
myOpenTrades[line,4] = riskClose;
myOpenTrades[line,5] = score;
myOpenTrades[line,6] = RSIComboScore;
myOpenTrades[line,7] = this.getSMATrend();
myOpenTrades[line,8] = Math.Round(NSRSICS(5, 15, 60, 240).Rsi200AVGPlot[0]);
myOpenTrades[line,9] = myReward;
myOpenTrades[line,10] = myRisk;
myOpenTrades[line,11] = 0;
}
protected override void OnMyChange()
{
foreach(double[] row in myOpenTrades)
{
if(Close[0] >= row[3] && row[11]==0)
{
Print("WIN:"+row[10]);
row[11]=1;
}
else if(Close[0] >= row[4] && row[11]==0)
{
Print("LOSE:"+row[9]);
row[11]=1;
}
}
{
I don't know why this is being downvoted, it seems like a legitimate question from a new user who made some effort.
To answer your question, an array of arrays is not the best choice, because from a logical organization perspective you don't have a "grid" (i.e. 2D array) of the same item, you have multiple items as one record, and an array of records. Not to mention that you appear to be trying to mix and match types; your array is declared as double but the first record type is an integer.
I would recommend using a class as follows:
class OpenTrades
{
public int Type;
public Bar CurrentBar;
public double Score;
// etc...
}
(This is assume that CurrentBar's type is Bar; you'll have to substitute Bar with whatever that type actually is.)
Then you would instantiate an array of your class like this:
OpenTrades[] myOpenTrades = new OpenTrades[11]; // This will create an array of 11 elements, indices 0 to 10
Now in your mymethod function you can assign values to each of your members.
myOpenTrades[line].Type = type;
myOpenTrades[line].Bar = CurrentBar;
myOpenTrades[line].Score = score;
// etc ...
I have an array:
String[] ay = {
"blah",
"blah number 2"
"etc" };
... But now I want to add to this array at a later time, but I see no option to do so. How can this be done? I keep getting a message saying that the String cannot be converted to String[].
Thank you
Use a List rather than an array:
List<string> list = new List<string>();
list.Add( "blah" ) ;
Then, later, if you really do need it as an array:
string[] ay = list.ToArray();
Arrays are of fixed size, so after it has been created, you can't change the size of it (without creating a new array object)
Use the List<string> instead of the array.
Arrays can't change their size after they are declared. Use collections instead. For example: List.
As everyone's already said, use List in the System.Collections.Generic namespace.
You could also use a Hashtable which will allow you to give each string a meaning, or "key" which gives you an easy way to pull out a certain string with a keyword. (as for keeping messages stored in memory space for whatever purpose.)
You could also Create a new array each time you add a value, make the new array 1 bigger than the old one, copy all the data from the first array into the 2nd array, and then add your new value in the last slot (Length - 1)
Then replace the old array with your new one.
It's the most manual way of doing it.
But List and Hashtable work perfectly well too.
If you don't need indexing a specific array element (usage of brackets), but you want to be able to efficiently add or remove elements, you could use LinkedList.
If you do need indexing
have a look at Dictionary data type also in the System.Collection
http://msdn.microsoft.com/en-us/library/xfhwa508.aspx
so you could do something like
Dictionary<int, string> dictionary = new Dictionary<int, string>();
dictionary.Add(1, "afljsd");
You can do this but I don't recommend it:
// Reallocates an array with a new size, and copies the contents
// of the old array to the new array.
// Arguments:
// oldArray the old array, to be reallocated.
// newSize the new array size.
// Returns A new array with the same contents.
public static System.Array ResizeArray (System.Array oldArray, int newSize) {
int oldSize = oldArray.Length;
System.Type elementType = oldArray.GetType().GetElementType();
System.Array newArray = System.Array.CreateInstance(elementType,newSize);
int preserveLength = System.Math.Min(oldSize,newSize);
if (preserveLength > 0)
System.Array.Copy (oldArray,newArray,preserveLength);
return newArray;
}
Here's an extension method to add the to arrays together and create a new string array
public static class StringArrayExtension
{
public static string[] GetStringArray (this string[] currentArray, string[] arrayToAdd)
{
List<String> list = new List<String>(currentArray);
list.AddRange(arrayToAdd);
return list.ToArray();
}
}
Let say I got this function :
void int Calculate(double[] array) {}
And in my main I got this array:
double[,] myArray = new double[3,3];
How can I call Calculate(...) ?
I try (that's don't compile) :
double[] mySingleArray = myArray[0];
What I want to avoid is unnecessary loop (for).
I declare a regular array, but if a jagged array or any other type of array works better, it's fine for me.
I use c# 3.5
First, let's declare your Calculate() method like this:
int Calculate(IEnumerable<double> doubles)
Don't worry, you can still pass an array to that code. You might also need IList<double>, but 9 times out of 10 the IEnumerable is good enough. The main thing is that this will let us use the yield keyword to slice up your array in an efficient way:
public static IEnumerable<T> Slice(this T[,] values)
{
return Slice(values, 0, 0);
}
public static IEnumerable<T> Slice(this T[,] values, int index)
{
return Slice(values, 0, index);
}
public static IEnumerable<T> Slice(this T[,] values, int dimension, int index)
{
int length = values.GetUpperBound(dimension);
int[] point = new int[values.Rank];
point[dimension] = index;
dimension = 1 - dimension;// only works for rank == 2
for (int i = 0; i < length; i++)
{
point[dimension] = i;
yield return (T)values.GetValue(point);
}
}
It still needs some work because it only works with rank 2 arrays, but it should be fine for the example you posted.
Now you can call your calculate function like this:
Calculate(myArray.Slice(0));
Note that due to the way IEnumerable and the yield statement work the for loop in the code I posted is essentially free. It won't run until you actually iterate the items in your Calculate method, and even there runs in a "just-in-time" fashion so that the whole algorithm remains O(n).
It gets even more interesting when you share what your Calculate method is doing. You might be able to express it as a simple Aggregate + lambda expression. For example, let's say your calculate method returned the number of items > 5:
myArray.Slice(0).Count(x => x > 5);
Or say it summed all the items:
myArray.Slice().Sum();
A jagged array works the way you want:
double[][] jaggedArray = new double[][100];
for (int i = 0; i < jaggedArray.Length; ++i)
jaggedArray[i] = new double[100];
myFunction(jaggedArray[0]);
You can have different sizes for each array in this way.
A jagged array would let you split out the first array!
The Slice() method given above will get you a single row from your array, which seems to match the sample given in your question.
However, if you want a one dimensional array that contains all the elements in the rectangular array, you can use something like this, which is also O(n).
public static T[] Flatten<T>(this T[,] array)
where T : struct
{
int size = Marshal.SizeOf(array[0, 0]);
int totalSize = Buffer.ByteLength(array);
T[] result = new T[totalSize / size];
Buffer.BlockCopy(array, 0, result, 0, totalSize);
return result;
}